<?php

namespace control;

/*
我的桌面
*/

use JetBrains\PhpStorm\ArrayShape;

class homepageClass extends adIndexClass
{
    private const title = '我的桌面';

    /*返回网页*/
    public function home(): string
    {
//		$menuType = $this->get('menuType') ?: '';//菜单类型
//		$html     = match ($menuType) {
//			'人力资源' => $this->personnelHomePage(),
//			'行政管理' => $this->administrationHomePage(),
//			'客户管理' => $this->clientHomePage(),
//			'供应链'   => $this->erpHomePage(),
//			'生产制造' => $this->produceHomePage(),
//			'财务会计' => $this->accountingHomePage(),
//			default    => '',
//		};
//		$html     = $html ?: $this->defaultHomePage();

        /***初始化导入模板***/
        /*$initFlag = static::rGet(self::$user['uid'] . 'Init');
        if ($initFlag != 1) {
            importTemplateClass::importTemplateInit();
            importTemplateClass::exportTemplateInit();
            static::rSet(self::$user['uid'] . 'Init', 1, 3600 * 8);
        }*/
        $html = $this->defaultHomePage();
        return head('ad') . $this->adheader([lang('public.index')]) . $html . warn() . $this->adfooter();
    }


    /**
     * 财务会计主页
     */
    private function accountingHomePage(): string
    {
        // 搜索文本框
        $searchTxt =
            self::searchText([
                'click'   => "cardSearch(this)",
                'search'  => true,
                "name"    => "month",
                "title"   => "时间段",
                "class"   => "line28 width150",
                "value"   => date("Y-m") . ' ~ ' . date("Y-m"),
                'laydate' => ['range' => '~', 'type' => 'month'],
            ]);
        $subject   =
            selectMultiple([
                "name"     => "subjectId",
                "table"    => "subject",
                'where'    => " coid = '" . self::$coid . "' and code in ('5601','5602','5603')",
                'class'    => " right line28 width150 m-r-10",
                'sqlId'    => 'id',
                'sqlField' => 'name',
                'title'    => '费用科目'
            ]);
        return <<<eof
<style>
.quarter {
    width: 16%;
}
.fs-label {
    height: 16px;
    padding: 4px;
    line-height: 16px;
    color: #757575;
}
.m-r-10{
    margin-right: 10px;
}
</style>
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<div class="home-warp">
    <div class="left-box">
        <div class="chart-widget">
            <p class="chart-title">业务流程图</p>
            <div id="container" class="canvas"></div>
        </div>
    </div>
    <div class="right-box">
        <div class="data-widget">
            {$this->backlog()}
        </div>
        <div style="overflow: hidden">
            <div class="data-widget">
                {$this->message()}
            </div>
        </div>
    </div>
    <div class="data-widget left m-t-0" style="width: 96.6%;">
        <form name="boardFinanceForm" data-fun="boardFinance" data-cla="homepage"><span class="title-card">数据看板</span>{$searchTxt}</form>
        <ul class="revenue" id="boardFinanceHtml">
            <li class="quarter left vertical-line">
                <div class="title-card-li-content">
                   <div>利润总额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                <div class="title-card-li-content">
                   <div>现金金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                 <div class="title-card-li-content">
                   <div>银行卡余额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
             <div class="title-card-li-content">
                   <div>存货</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
             <div class="title-card-li-content">
                   <div>应收账款</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
             <div class="title-card-li-content">
                   <div>应付账款</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
        </ul>
    </div>
    <div class="data-widget left" style="width: 96.6%;">
        <form name="profitReceivableTrendForm" data-fun="profitReceivableTrend" data-cla="homepage"><span class="title-card">应收与利润趋势</span>{$searchTxt}</form>
        <div class="data-box-show" id="profitReceivableTrendHtml"></div>
    </div>
    <div class="half left data-widget">
        <form name="expenseItemsForm" data-fun="expenseItems" data-cla="homepage"><span class="title-card">费用项目分布</span>{$searchTxt}{$subject}</form>
        <div class="data-box-show" id="expenseItemsHtml"></div>
    </div>
    <div class="half left data-widget">
        <form name="departmentalChargeForm" data-fun="departmentalCharge" data-cla="homepage"><span class="title-card">部门费用分布</span>{$searchTxt}</form>
        <div class="data-box-show" id="departmentalChargeHtml"></div>
    </div>
</div>
{$this->flowChart('container', 'accountingData')}
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<script>
function search_line(form,cla,fun) {
     $("#" + fun + "Html").html("数据查询中，请稍后。。。");
     //串联表单
        var formName = form.split(",");
        var serialize = "";
        var a = "";
        for (var i = 0; i < formName.length; i++) {
            if (serialize == "") {
                a = "";
            } else {
                a = "&";
            }
            if (formName[i] != "") {
                serialize += a + $("[name=" + formName[i] + "]").serialize();
            }
        }
    $.post(root + "control/adIndex.html?cla=" + cla + "&fun=" + fun, serialize, function (data) {
         $("#" + fun + "Html").html(data.html);
    }, "json");
}

/**
* 看板搜索
*/
function cardSearch(obj){
    let searchform = $(obj).parents("form");
    let formName = searchform.attr('name');
    let fun = searchform.data('fun');
    let cla = searchform.data('cla');
    search_line(formName,cla, fun)
}

$(function() {
    search_line('boardFinanceForm','homepage', 'boardFinance')
    search_line('profitReceivableTrendForm','homepage','profitReceivableTrend');
    search_line('expenseItemsForm','homepage','expenseItems')
    search_line('departmentalChargeForm','homepage','departmentalCharge')
})
</script>
eof;
    }

    /**
     * 设置显示字段
     * @return bool|string
     */
    public function tableFieldFrame(): bool|string
    {
        $pageStr        = $this->post('pageStr');
        $fieldNameArray = $this->post('fieldName') ? explode('[#]', $this->post('fieldName')) : [];
        // 查找自定义显示字段
        $userSetting = query('user_setting', generateWhere([
            'type' => '自定义显示字段',
            'page' => $pageStr,
            'stid' => self::$stid,
        ]), 'id, value');
        $pageFields  = $fieldNameArray;//默认展示全部
        if ($userSetting['id']) {
            $setting    = json_decode($userSetting['value'], true);
            $pageFields = (array)$setting['field'];
        }
        $show_li = $hidden_li = '';
        foreach ($fieldNameArray as $index => $fieldName) {
            if (in_array($fieldName, $pageFields)) {
                $show_li .= "<li data-list='$index'><span data-name='$fieldName'>$fieldName</span><span class='del_text leftDel'>×</span></li>";
            } else {
                $hidden_li .= "<li data-list='$index'><span data-name='$fieldName'>$fieldName</span><span class='del_text rightDel'>×</span></li>";
            }
        }
        //生成表单
        $html = <<<eof
<div class="fieldFrame">
    <div class="left-frame">
        <div class="frame-title">显示字段</div>
        <div id="showContent" class="frame-content">
            <ul class='menu_list'>
               $show_li
            </ul>
        </div>
    </div>
    <div class="right-frame">
        <div class="frame-title">不显示字段</div>
        <div id="hideContent" class="frame-content">
             <ul class='menu_list'>
                $hidden_li
             </ul>
        </div>
    </div>
</div>
<div><button data-page="$pageStr" class="button button-confirm" type="button" id="fieldFrameBtn">确认</button></div>
<style>
.fieldFrame{width: 640px;height: 370px;margin: 8px auto;border: 1px solid #cbcbcb;border-radius: 4px;overflow: hidden;padding: 10px}
.left-frame{display: inline-block;width: 300px}
.right-frame{display: inline-block;width: 300px;margin-left: 20px}
.frame-title{font-size: 14px;color: grey}
.frame-content{border: 1px dashed #0070cc59;height: 330px;padding: 4px;overflow: auto;}
.menu_list>li{width:250px;background-color: #F2F2F2;padding: 3px 7px;margin: 4px auto;line-height: normal}
.menu_list>li>span:first-child{width:220px;display: inline-block;overflow: hidden; white-space: nowrap;text-overflow:ellipsis}
.del_text{float: right;margin-right: 10px;font-weight: 400;cursor:pointer;font-size: 20px;color: #AAAAAA;font-kerning: normal;}
.del_text:hover{color: red}
.button-confirm{width: 80px;float: right;margin-right: 30px;margin-top: 10px;}
</style>
<script>
$("#showContent").on('click','.leftDel',function() {
    let _this = $(this);
    let name = _this.prev().data('name');
    let list = _this.parent().data('list');
    let menu_list = $("#hideContent .menu_list")
    menu_list.append("<li data-list='"+list+"'><span data-name='"+name+"'>"+name+"</span><span class='del_text rightDel'>×</span></li>");
    sortElement(menu_list)
    _this.parent().remove();
})
$("#hideContent").on('click','.rightDel',function() {
    let _this = $(this);
    let name = _this.prev().data('name');
    let list = _this.parent().data('list');
    let menu_list = $("#showContent .menu_list")
    menu_list.append("<li data-list='"+list+"'><span data-name='"+name+"'>"+name+"</span><span class='del_text leftDel'>×</span></li>");
     sortElement(menu_list)
    _this.parent().remove();
})
$("#fieldFrameBtn").click(function (){
    let fields = [];
    let pageStr = $(this).data('page');
    $("#showContent .menu_list li span[data-name]").each(function() {
       fields.push($(this).data('name'));
    })
    $.post(root + 'control/adIndex.html?cla=homepage&fun=setField', {page:pageStr,fields:fields}, function (res) {
        if (res.code === 0) {
            msg(res.warn, 'error')
        }else{
            let url = $("#renovate").attr("url");
            if (url) {
                //页卡切换时会保存菜单关键字在renovate的url中
                location.href = url;
            } else {
                location.reload();
            }
        }
    }, 'json')
})

function sortElement(container){
  var items = container.find('li').get();  // 使用.get()将jQuery对象转换为原生的DOM元素数组
  items.sort(function(a, b) {
    var orderA = $(a).data('list');  // 获取元素的data-order属性值
    var orderB = $(b).data('list');  // 获取元素的data-order属性值
    return orderA - orderB;  // 对属性值进行排序，从小到大
  });
  // 重新将排序后的元素添加到容器中
  container.empty();  // 清空容器
  $.each(items, function(index, item) {
    container.append(item);  // 将每个元素添加回容器
  });
}
</script>
eof;
        //返回
        return $this->layer(array("title" => "自定义显示字段", 'zindex' => 100, "height" => 500, "width" => 700, "html" => $html));
    }

    /**
     * 桌面数据看板
     */
    public function boardFinance(): bool|string
    {
        $month = $this->post('month');
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = date('Y-m');
            $timeArr[1] = date('Y-m');
        }
        $accountRule  = companyClass::returnRule(1);
        $result       = $this->totalProfit('利润总额', $month, $accountRule);
        $profit       = $result['monthBalance'];
        $json['html'] = '';
        //利润总额
        $text         = $profit > 10000 ? '万' : '';
        $money        = round($profit > 10000 ? ($profit / 10000) : $profit, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                               <div>利润总额</div>
                                <div><span class="title-card-li-money">￥{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //现金金额
        $cash         = $this->bookkeepingBalance($month, '现金');
        $text         = $cash > 10000 ? '万' : '';
        $money        = $cash > 10000 ? round(($cash / 10000), 2) : round($cash, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                                <div>现金余额</div>
                                <div><span class="title-card-li-money">￥{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //银行卡余额
        $bank         = $this->bookkeepingBalance($month, '银行存款');
        $text         = $bank > 10000 ? '万' : '';
        $money        = round($bank > 10000 ? ($bank / 10000) : $bank, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                               <div>银行卡余额</div>
                                <div><span class="title-card-li-money">￥{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //存货
        $page                = find(array(
            "table" => "subject as a join voucher_detail as b on a.id = b.subjectId join voucher as c on b.orderId =c.id  where a.coid = '" . self::$coid . "' and c.isTemplate = '否'  UNION select b.materialId from subject as a join subject_assist as b on a.id = b.orderId",
            "field" => "b.materialId",
            "where" => "a.coid = '" . self::$coid . "'  and b.initMoney >0"
        ));
        $workFlow            = '存货';
        $projectBalanceClass = new projectBalanceClass();
        $jie                 = 0;
        foreach ($page['array'] as $array) {
            $targetId = $array['materialId'];
            //$initResult = $projectBalanceClass->initMoney($workFlow, $targetId, $timeArr[0],$this->post('subjectId'));
            $monthResult = $projectBalanceClass->monthBalance($workFlow, $targetId, $timeArr[0], $timeArr[1], $this->post('subjectId'));
            //$balance = $projectBalanceClass->balance($workFlow, $targetId, $timeArr[1],$this->post('subjectId'));
            $jie += $monthResult['jieMoney'];
        }
        $text         = $jie > 10000 ? '万' : '';
        $money        = round($jie > 10000 ? ($jie / 10000) : $jie, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                                <div>存货</div>
                                <div><span class="title-card-li-money">{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //应收账款
        $and = "";
        if ($month) {
            $and .= self::timeComparison($month, 'month', 'targetDate');
        }
        $receivable   = find(array(
            'table'  => 'record',
            'single' => " coid = '" . self::$coid . "' and type = '客户' " . $and,
            'field'  => "ifnull(sum(balance),0) as money"
        ))['money'] ?: 0;
        $text         = $receivable > 10000 ? '万' : '';
        $money        = round($receivable > 10000 ? ($receivable / 10000) : $receivable, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                                <div>应收账款</div>
                                <div><span class="title-card-li-money">{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //应付账款
        $payable      = find(array(
            'table'  => 'record',
            'single' => " coid = '" . self::$coid . "' and type = '供应商' " . $and,
            'field'  => "ifnull(sum(balance),0) as money"
        ))['money'] ?: 0;
        $text         = $payable > 10000 ? '万' : '';
        $money        = round($payable > 10000 ? ($payable / 10000) : $payable, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                                <div>应付账款</div>
                                <div><span class="title-card-li-money">{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;

        return json_encode($json, 320);
    }

    /*资金总账*/
    public function bookkeepingBalance($month, $type)
    {
        //like查询数组
        $like = array();
        //全等查询数组
        $equal     = array(
            'coid' => self::$coid,
            'type' => $type,
        );
        $and       = " and subjectId !=''";
        $timeWhere = $voucherWhere = '';
        $startDate = '';
        if ($month) {
            $data         = explode('~', $month);
            $startDate    = trim($data[0]);
            $timeWhere    .= self::timeComparison($month, 'month', field: 'recordDate');
            $voucherWhere .= self::timeComparison($month, 'month', field: 'a.recordDate');
        }
        //获取查询结果
        $where   = search(array("like" => $like, "=" => $equal)) . $and;
        $page    = find(array('table' => "account", 'where' => $where . " order by time asc", 'field' => "*"));
        $balance = 0; //余额
        foreach ($page['array'] as $array) {
            $subject = query('subject', "id = '$array[subjectId]'");
            if (!empty($subject['id'])) {
                $subjectJieInitMoney = find(array(
                    'table'  => 'voucher as a join voucher_detail as b on a.id = b.orderId',
                    'single' => "b.subjectId = '$array[subjectId]' and b.direction = '借' and a.isTemplate = '否' and a.coid = '" . self::$coid . "' and date_format(a.recordDate,'%Y-%m') <'$startDate'",
                    'field'  => "ifnull(sum(b.money),0) as money"
                ))['money'];
                $subjectDaiInitMoney = find(array(
                    'table'  => 'voucher as a join voucher_detail as b on a.id = b.orderId',
                    'single' => "b.subjectId = '$array[subjectId]' and b.direction = '贷' and a.isTemplate = '否' and a.coid = '" . self::$coid . "' and date_format(a.recordDate,'%Y-%m') <'$startDate'",
                    'field'  => "ifnull(sum(b.money),0) as money"
                ))['money'];
                $subjectInitMoney    = $subjectJieInitMoney - $subjectDaiInitMoney;
                if ($subject['direction'] == '借') {
                    $subjectInitMoney += $subject['initMoney'];
                } else {
                    $subjectInitMoney -= $subject['initMoney'];
                }
                $subjectInitMoney = self::centToYuan($subjectInitMoney);//科目期初金额

                $jieMoney = find(array(
                    'table'  => 'voucher as a join voucher_detail as b on a.id = b.orderId',
                    'single' => "b.subjectId = '$array[subjectId]' and b.direction = '借' and a.isTemplate = '否' and a.coid = '" . self::$coid . "'" . $voucherWhere,
                    'field'  => "ifnull(sum(b.money),0) as money"
                ))['money'];
                $daiMoney = find(array(
                    'table'  => 'voucher as a join voucher_detail as b on a.id = b.orderId',
                    'single' => "b.subjectId = '$array[subjectId]' and b.direction = '贷' and a.isTemplate = '否' and a.coid = '" . self::$coid . "'" . $voucherWhere,
                    'field'  => "ifnull(sum(b.money),0) as money"
                ))['money'];
                $jieMoney = self::centToYuan($jieMoney);
                $daiMoney = self::centToYuan($daiMoney);

                $initMoney = find(array(
                    'table'  => 'bookkeeping',
                    'single' => "accountId = '$array[id]' and date_format(recordDate,'%Y-%m') < '$startDate'",
                    'field'  => "ifnull(sum(income-expenses),0) as money"
                ))['money'];
                $initMoney += $array['initMoney'];

                $income  = find(array(
                    'table' => 'bookkeeping',
                    'where' => "accountId = '$array[id]'" . $timeWhere,
                    'sum'   => "income"
                ));
                $out     = find(array(
                    'table' => 'bookkeeping',
                    'where' => "accountId = '$array[id]'" . $timeWhere,
                    'sum'   => "expenses"
                ));
                $balance += ($subjectInitMoney + $jieMoney - $daiMoney) - ($initMoney + $income - $out);
            }
        }
        return $balance;
    }

    /**
     * @param $name
     * @param $month 时间区间
     * @param $accountRule
     * @return array
     */
    public function totalProfit($name, $month, $accountRule): array
    {
        $money = $monthMoney = 0;
        if ($name == '营业利润') {
            $result     = $this->balance('营业收入', $month);
            $all        = find(array(
                'table' => 'profit_income',
                'where' => "pid = '营业收入' and coid = '" . self::$coid . "'"
            ));
            $money      = $result['balance'];
            $monthMoney = $result['monthBalance'];
            if ($accountRule == 'enterpriseRule') {
                foreach ($all['array'] as $array) {
                    $result = $this->balance($array['name'], $month);
                    if (in_array($array['name'], ['投资收益', '公允价值变动收益'])) {
                        $money      += $result['balance'];
                        $monthMoney += $result['monthBalance'];
                    } else {
                        $money      -= $result['balance'];
                        $monthMoney -= $result['monthBalance'];
                    }
                }
            } elseif ($accountRule == 'smallEnterpriseRule') {
                foreach ($all['array'] as $array) {
                    $result = $this->balance($array['name'], $month);
                    if ($array['name'] == '投资收益') {
                        $money      += $result['balance'];
                        $monthMoney += $result['monthBalance'];
                    } else {
                        $money      -= $result['balance'];
                        $monthMoney -= $result['monthBalance'];
                    }
                }
            }
        } elseif ($name == '利润总额') {
            $result     = $this->totalProfit('营业利润', $month, $accountRule);
            $money      = $result['balance'];
            $monthMoney = $result['monthBalance'];
            $all        = find(array(
                'table' => 'profit_income',
                'where' => "pid = '营业利润' and coid = '" . self::$coid . "'"
            ));
            if ($accountRule == 'enterpriseRule') {
                foreach ($all['array'] as $array) {
                    $result = $this->balance($array['name'], $month);
                    if (in_array($array['name'], ['营业外收入'])) {
                        $money      += $result['balance'];
                        $monthMoney += $result['monthBalance'];
                    } else {
                        $money      -= $result['balance'];
                        $monthMoney -= $result['monthBalance'];
                    }
                }
            } elseif ($accountRule == 'smallEnterpriseRule') {
                foreach ($all['array'] as $array) {
                    $result = $this->balance($array['name'], $month);
                    if (in_array($array['name'], ['营业外收入', '政府补助'])) {
                        $money      += $result['balance'];
                        $monthMoney += $result['monthBalance'];
                    } else {
                        $money      -= $result['balance'];
                        $monthMoney -= $result['monthBalance'];
                    }
                }
            }
        } elseif ($name == '净利润') {
            $result     = $this->totalProfit('利润总额', $month, $accountRule);
            $money      = $result['balance'];
            $monthMoney = $result['monthBalance'];
            $all        = find(array(
                'table' => 'profit_income',
                'where' => "pid = '利润总额' and coid = '" . self::$coid . "'"
            ));
            foreach ($all['array'] as $array) {
                $result     = $this->balance($array['name'], $month);
                $money      -= $result['balance'];
                $monthMoney -= $result['monthBalance'];
            }
        } elseif ($name == '其他综合收益的税后净额') {
            $money      = 0;
            $monthMoney = 0;
        } elseif ($name == '综合收益总额') {
            $result     = $this->totalProfit('净利润', $month, $accountRule);
            $money      = $result['balance'];
            $monthMoney = $result['monthBalance'];
        }
        return ['balance' => $money, 'monthBalance' => $monthMoney];
    }

    /**
     * 期末余额
     */
    public function balance($name, $month)
    {
        $all          = find(array(
            'table' => 'profit_income_formula',
            'where' => "name = '$name' and coid = '" . self::$coid . "'"
        ));
        $monthBalance = 0;//本期金额
        $multObj      = new multiColumnAccountClass();
        foreach ($all['array'] as $array) {
            $childMonthBalance = 0;
            $columns           = [];
            $multObj->loopSubjectIds($array['subjectId'], $columns);
            foreach ($columns as $subjectId) {
                $childMonthBalance += $this->sectionMoney($subjectId, $month, $array['rule']);
            }
            $monthBalance = match ($array['symbol']) {
                '-' => $monthBalance - $childMonthBalance,
                default => $monthBalance + $childMonthBalance
            };
        }
        return ['balance' => 0, 'monthBalance' => $monthBalance];
    }

    /**
     * 本期金额
     */
    public function sectionMoney($subjectId, $month, $rule): float|int
    {
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = date('Y-m');
            $timeArr[1] = date('Y-m');
        }
        $where            = " and date_format(a.recordDate,'%Y-%m') >= '$timeArr[0]' and date_format(a.recordDate,'%Y-%m') <= '$timeArr[1]' and b.subjectId = '$subjectId'";
        $jieInit          = find(array(
            "table"  => "voucher as a join voucher_detail as b on a.id = b.orderId",
            'field'  => "ifnull(sum(b.money),0) as money",
            "single" => "a.isTemplate = '否' and a.coid = '" . self::$coid . "' and b.direction = '借'" . $where . voucherClass::joinWhere()
        ));
        $daiInit          = find(array(
            "table"  => "voucher as a join voucher_detail as b on a.id = b.orderId",
            'field'  => "ifnull(sum(b.money),0) as money",
            "single" => "a.isTemplate = '否' and a.coid = '" . self::$coid . "' and b.direction = '贷'" . $where . voucherClass::joinWhere()
        ));
        $jieInit['money'] = self::centToYuan($jieInit['money']);
        $daiInit['money'] = self::centToYuan($daiInit['money']);
        switch ($rule) {
            case '贷方发生额':
                $balance = $daiInit['money'];
                break;
            case '借方发生额':
                $balance = $jieInit['money'];
                break;
            case '期初余额':
                $subject    = query('subject', "id = '$subjectId'");
                $initResult = $this->initMoney($subject, $timeArr[0]);
                $balance    = $initResult['jieMoney'] ?: $initResult['daiMoney'];
                break;
            default://发生额
                $balance = $jieInit['money'] ?: $daiInit['money'];
                break;
        }
        return $balance;
    }

    /**
     * 期初余额
     *
     * @param $subject
     * @param $startDate
     * @return array
     */
    public function initMoney($subject, $startDate): array
    {
        //借方
        $jieInit = find(array(
            "table"  => "voucher as a join voucher_detail as b on a.id = b.orderId",
            'field'  => "ifnull(sum(b.money),0) as money,ifnull(sum(b.voucherNum),0) as num",
            "single" => "a.isTemplate = '否' and a.coid = '" . self::$coid . "' and b.subjectId = '$subject[id]' and b.direction = '借' and date_format(a.recordDate,'%Y-%m') < '$startDate'" . voucherClass::joinWhere()
        ));
        //贷方
        $daiInit = find(array(
            "table"  => "voucher as a join voucher_detail as b on a.id = b.orderId",
            'field'  => "ifnull(sum(b.money),0) as money,ifnull(sum(b.voucherNum),0) as num",
            "single" => "a.isTemplate = '否' and a.coid = '" . self::$coid . "' and b.subjectId = '$subject[id]' and b.direction = '贷' and date_format(a.recordDate,'%Y-%m') < '$startDate'" . voucherClass::joinWhere()
        ));
        //期初数量
        $initNum = find(array(
            'table' => 'subject_assist',
            "where" => "orderId = '$subject[id]'",
            'sum'   => "initNum"
        ));
        if ($subject['direction'] == '借') {
            $jieInit['money'] += $subject['initMoney'];
            $jieInit['num']   = $jieInit['num'] + $initNum;
        } else {
            $daiInit['num']   = $daiInit['num'] + $initNum;
            $daiInit['money'] += $subject['initMoney'];
        }
        $jieInit['money'] = self::centToYuan($jieInit['money']);
        $daiInit['money'] = self::centToYuan($daiInit['money']);
        if ($jieInit['money'] > $daiInit['money']) {
            $jieMoney = $jieInit['money'] - $daiInit['money'];
            $daiMoney = 0;
        } else {
            $daiMoney = abs($jieInit['money'] - $daiInit['money']);
            $jieMoney = 0;
        }
        $result = [
            'num'      => $jieInit['num'] - $daiInit['num'],
            'price'    => abs(accountDetailsClass::division($jieInit['money'] - $daiInit['money'], $jieInit['num'] - $daiInit['num'])),
            'jieMoney' => $jieMoney,
            'daiMoney' => $daiMoney,
        ];
        /*if (self::$isFormat){
            $result = accountDetailsClass::formatArrayNumber($result);
        }*/
        return $result;
    }


    /**
     * 营收与利润趋势
     *
     * @return bool|string
     */
    public function profitReceivableTrend(): bool|string
    {
        $month = $this->post('month');
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = date('Y-01');
            $timeArr[1] = date('Y-m');
        }
        //时间段数组
        $res               = [];
        $m                 = $timeArr[0];
        $profitIncomeClass = new profitIncomeClass();
        $accountRule       = companyClass::returnRule(1);
        while ($m <= $timeArr[1]) {
            $income = $profitIncomeClass->balance('营业收入', $m);
            $profit = $profitIncomeClass->totalProfit('利润总额', $month, $accountRule);
            $res[]  = [
                'month'  => $m,
                'income' => round($income['monthBalance'] / 10000, 2),
                'profit' => round($profit['monthBalance'] / 10000, 2),
            ];
            $m      = date("Y-m", strtotime($m . '-01' . " +1 month"));
        }
        $data         = [
            "subtext" => '单位：万元',
            "name"    => array_column($res, 'month'),
            "series"  => [
                [
                    'name' => '营业收入',
                    'data' => array_column($res, 'income'),
                ],
                [
                    'name' => '利润总额',
                    'data' => array_column($res, 'profit'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data, 'bar');
        return json_encode($json, 320);
    }

    /**
     * 费用项目分布
     *
     * @return bool|string
     */
    public function expenseItems(): bool|string
    {
        $month     = $this->post('month');
        $subjectId = $this->post('subjectId');
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = date('Y-m');
            $timeArr[1] = date('Y-m');
        }
        if (empty($subjectId)) {
            $result = find(array(
                "table" => "subject",
                "field" => "id,name",
                "where" => " coid = '" . self::$coid . "' and code in ('5601','5602','5603') "
            ));
        } else {
            $result = find(array(
                "table" => "subject",
                "field" => "id,name",
                "where" => " coid = '" . self::$coid . "' and pid = '$subjectId' "
            ));
        }
        $res                      = [];
        $subjectBalanceClass      = new subjectBalanceClass();
        $inventoryReportFormClass = new inventoryReportFormClass();
        foreach ((array)$result['array'] as $array) {
            //本期合计
            $monthResult = $subjectBalanceClass->monthBalance($timeArr[0], $timeArr[1], $array['id']);
            $res[]       = ['name' => $array['name'], 'data' => round($monthResult['daiMoney'] / 10000, 2)];
        }
        $data         = [
            "text"    => '',
            "subtext" => '单位：万元',
            "series"  => $res,
        ];
        $json['html'] = $inventoryReportFormClass->pie($data);
        return json_encode($json, 320);
    }

    /**
     * 部门费用分布 - 返回数据
     */
    public function departmentalCharge(): bool|string
    {
        $month = $this->post('month');
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = date('Y-m');
            $timeArr[1] = date('Y-m');
        }
        $department          = find(array(
            "table" => "department",
            "field" => "name,id",
            "where" => "1=1 order by orderNo asc"
        ));
        $projectBalanceClass = new projectBalanceClass();
        $res                 = [];
        foreach ((array)$department['array'] as $array) {
            /*$and = " and departmentId !='' and departmentId = '" . $array['id'] . "'";
            $total = 0;
            $page = find(array("table"=>"subject as a join voucher_detail as b on a.id = b.subjectId join voucher as c on b.orderId =c.id  where a.coid = '".self::$coid."' and c.isTemplate = '否'  {$and} UNION select b.departmentId from subject as a join subject_assist as b on a.id = b.orderId","field"=>"b.departmentId","where"=>"a.coid = '".self::$coid."'  and b.initMoney !=0 {$and}"));
            $workFlow = '部门';

            foreach ($page['array'] as $array) {
                $targetId = $array['departmentId'];
                //$initResult = $projectBalanceClass->initMoney($workFlow, $targetId, $timeArr[0],$this->post('subjectId'));
                $monthResult = $projectBalanceClass->monthBalance($workFlow, $targetId, $timeArr[0], $timeArr[1],$this->post('subjectId'));
                //$balance = $projectBalanceClass->balance($workFlow, $targetId, $timeArr[1],$this->post('subjectId'));
                $total += $monthResult['daiMoney'];
            }*/
            $monthResult = $projectBalanceClass->monthBalance('部门', $array['id'], $timeArr[0], $timeArr[1], $this->post('subjectId'));
            //$balance = $projectBalanceClass->balance($workFlow, $targetId, $timeArr[1],$this->post('subjectId'));
            $total = $monthResult['daiMoney'];
            $res   = [
                'name'  => $array['name'],
                'money' => round($total / 10000, 2),
            ];
        }
        $data         = [
            "subtext" => '单位：万元',
            "name"    => array_column($res, 'name'),
            "series"  => [
                [
                    'name' => '实际发生',
                    'data' => array_column($res, 'money'),
                ],
            ],
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }

    public function accountingData(): bool|string
    {
        $json['result'] = [
            /**********凭证********/
            [
                'type'   => 'group',
                'id'     => 'voucherGroup',
                'name'   => '',
                'x'      => 90,
                'y'      => 75,
                'width'  => 150,
                'height' => 450,
            ],
            $this->nodeData(['page' => 'voucherEdit', 'x' => 130, 'y' => 100, 'name' => '录凭证', 'file' => 'finance']),
            $this->nodeData(['page' => 'voucher', 'x' => 130, 'y' => 250, 'name' => '查看凭证', 'file' => 'finance']),
            $this->nodeData(['page' => 'voucherStatistics', 'x' => 130, 'y' => 400, 'name' => '凭证汇总', 'file' => 'finance']),
            /**********工资********/
            [
                'type'   => 'group',
                'id'     => 'wages',
                'name'   => '',
                'x'      => 300,
                'y'      => 75,
                'width'  => 150,
                'height' => 150,
            ],
            $this->nodeData(['page' => 'salary', 'x' => 340, 'y' => 100, 'name' => '工资表', 'file' => 'finance']),
            /*********固定资产*******/
            [
                'type'   => 'group',
                'id'     => 'fixedAssets',
                'name'   => '',
                'x'      => 300,
                'y'      => 375,
                'width'  => 150,
                'height' => 150,
            ],
            $this->nodeData(['page' => 'assetList', 'x' => 340, 'y' => 400, 'name' => '固定资产', 'title' => '固定资产清单', 'file' => 'finance']),
            /*********明细账*******/
            [
                'type'   => 'group',
                'id'     => 'subLedger',
                'name'   => '',
                'x'      => 510,
                'y'      => 75,
                'width'  => 270,
                'height' => 450,
            ],
            $this->nodeData(['page' => 'accountDetails', 'x' => 550, 'y' => 100, 'name' => '明细账', 'file' => 'finance']),
            $this->nodeData(['page' => 'projectDetails', 'x' => 670, 'y' => 100, 'name' => '项目明细账', 'title' => '核算项目明细账', 'file' => 'finance']),
            $this->nodeData(['page' => 'accountTotal', 'x' => 550, 'y' => 250, 'name' => '总账', 'file' => 'finance']),
            $this->nodeData(['page' => 'projectBalance', 'x' => 670, 'y' => 250, 'name' => '项目余额表', 'title' => '核算项目余额表', 'file' => 'finance']),
            $this->nodeData(['page' => 'subjectBalance', 'x' => 550, 'y' => 400, 'name' => '科目余额表', 'file' => 'finance']),
            $this->nodeData(['page' => 'multiColumnAccount', 'x' => 670, 'y' => 400, 'name' => '多栏账', 'file' => 'finance']),
            /*********************/
            $this->nodeData(['page' => 'carryover', 'x' => 840, 'y' => 170, 'name' => '期末结转', 'file' => 'finance']),
            $this->nodeData(['page' => 'checkout', 'x' => 840, 'y' => 330, 'name' => '结账', 'file' => 'finance']),
            /*********汇总表*******/
            [
                'type'   => 'group',
                'id'     => 'summary',
                'name'   => '',
                'x'      => 980,
                'y'      => 75,
                'width'  => 150,
                'height' => 450,
            ],
            $this->nodeData(['page' => 'assetDebt', 'x' => 1020, 'y' => 100, 'name' => '资产负债表', 'file' => 'finance']),
            $this->nodeData(['page' => 'profitIncome', 'x' => 1020, 'y' => 250, 'name' => '利润表', 'file' => 'finance']),
            $this->nodeData(['page' => 'cashFlow', 'x' => 1020, 'y' => 400, 'name' => '现金流量表', 'file' => 'finance']),
            /*********流程表*******/
            [
                'type'   => 'group',
                'id'     => 'flow',
                'name'   => '',
                'x'      => 90,
                'y'      => 585,
                'width'  => 690,
                'height' => 450,
            ],
            $this->nodeData(['page' => 'saleSendOrder', 'x' => 130, 'y' => 610, 'name' => '销售发货单', 'file' => 'finance']),
            $this->nodeData(['page' => 'incomeDetails', 'x' => 130, 'y' => 760, 'name' => '应收账款', 'title' => '应收账款明细表', 'file' => 'finance']),
            $this->nodeData(['page' => 'inReceipt', 'x' => 130, 'y' => 910, 'name' => '收款单', 'file' => 'finance']),
            $this->nodeData(['page' => 'writeOffOrder', 'x' => 260, 'y' => 760, 'name' => '核销单', 'file' => 'finance']),
            $this->nodeData(['page' => 'purchaseGetOrder', 'x' => 390, 'y' => 610, 'name' => '采购收货单', 'file' => 'finance']),
            $this->nodeData(['page' => 'payDetails', 'x' => 390, 'y' => 760, 'name' => '应付账款', 'title' => '应付账款明细表', 'file' => 'finance']),
            $this->nodeData(['page' => 'payReceipt', 'x' => 390, 'y' => 910, 'name' => '付款单', 'file' => 'finance']),
            $this->nodeData(['page' => 'outsourceSettle', 'x' => 520, 'y' => 610, 'name' => '委外结算单', 'file' => 'finance']),
            $this->nodeData(['page' => 'otherInReceipt', 'x' => 520, 'y' => 910, 'name' => '其他收入单', 'file' => 'finance']),
            $this->nodeData(['page' => 'transferReceipt', 'x' => 650, 'y' => 760, 'name' => '转账单', 'file' => 'finance']),
            $this->nodeData(['page' => 'otherOutReceipt', 'x' => 650, 'y' => 910, 'name' => '其他支出单', 'file' => 'finance']),
            /*********记账*******/
            [
                'type'   => 'group',
                'id'     => 'bookkeeping',
                'name'   => '',
                'x'      => 860,
                'y'      => 585,
                'width'  => 270,
                'height' => 450,
            ],
            $this->nodeData(['page' => 'cashBook', 'x' => 900, 'y' => 610, 'name' => '现金日记账', 'file' => 'finance']),
            $this->nodeData(['page' => 'financialReport', 'x' => 1030, 'y' => 610, 'name' => '资金报表', 'file' => 'finance']),

            $this->nodeData(['page' => 'bankBook', 'x' => 900, 'y' => 760, 'name' => '银行日记账', 'file' => 'finance']),
            $this->nodeData(['page' => 'generalAccount', 'x' => 1030, 'y' => 760, 'name' => '核对总账', 'file' => 'finance']),

            $this->nodeData(['page' => 'innerTransfer', 'x' => 900, 'y' => 910, 'name' => '内部转账', 'file' => 'finance']),
        ];
        $json['link']   = [
            //group link
            ['source' => 'voucherGroup', 'target' => 'subLedger', 'vertices' => []],
            ['source' => 'wages', 'target' => 'voucherGroup', 'vertices' => []],
            ['source' => 'fixedAssets', 'target' => 'voucherGroup', 'vertices' => []],
            ['source' => 'flow', 'target' => 'bookkeeping', 'vertices' => []],
            //node link
            ['source' => 'subLedger', 'target' => 'carryover', 'vertices' => []],
            ['source' => 'carryover', 'target' => 'checkout', 'vertices' => []],
            ['source' => 'checkout', 'target' => 'summary', 'vertices' => []],
            ['source' => 'bookkeeping', 'target' => 'checkout', 'vertices' => []],

            ['source' => 'saleSendOrder', 'target' => 'incomeDetails', 'vertices' => []],
            ['source' => 'inReceipt', 'target' => 'incomeDetails', 'vertices' => []],
            ['source' => 'incomeDetails', 'target' => 'writeOffOrder', 'vertices' => []],
            ['source' => 'payDetails', 'target' => 'writeOffOrder', 'vertices' => []],
            ['source' => 'purchaseGetOrder', 'target' => 'payDetails', 'vertices' => []],
            ['source' => 'payReceipt', 'target' => 'payDetails', 'vertices' => []],
            ['source' => 'outsourceSettle', 'target' => 'payDetails', 'vertices' => [['x' => 555, 'y' => 800]]],
        ];
        return json_encode($json, 320);
    }

    /**
     * 供应链主页
     */
    private function erpHomePage(): string
    {
        // 搜索文本框
        $searchTxt =
            self::searchText([
                'click'   => "cardSearch(this)",
                'search'  => true,
                "name"    => "date",
                "title"   => "时间段",
                "class"   => "line28 width200",
                "value"   => '',
                'laydate' => ['range' => '~', 'type' => 'date'],
            ]);
        return <<<eof
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<div class="home-warp">
    <div class="left-box">
        <div class="chart-widget">
            <p class="chart-title">业务流程图</p>
            <div id="container" class="canvas"></div>
        </div>
    </div>
    <div class="right-box">
        <div class="data-widget">
            {$this->backlog()}
        </div>
        <div style="overflow: hidden">
            <div class="data-widget">
                {$this->alertMessage()}
            </div>
        </div>
    </div>
    <div class="data-widget left m-t-0" style="width: 96.6%;">
        <form name="boardHomeForm" data-fun="boardHome" data-cla="salesReportForm"><span class="title-card">数据看板</span>{$searchTxt}</form>
        <ul class="revenue" id="boardHomeHtml">
            <li class="quarter left vertical-line">
                <div class="title-card-li-content">
                   <div>销售金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                <div class="title-card-li-content">
                   <div>回款金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                 <div class="title-card-li-content">
                   <div>材料采购金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
             <div class="title-card-li-content">
                   <div>库存金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
        </ul>
    </div>
    <div class="data-widget left" style="width: 96.6%;">
        <form name="salesStatisticsForm" data-fun="salesStatistics" data-cla="salesReportForm"><span class="title-card">销售统计</span>{$searchTxt}</form>
        <div class="data-box-show" id="salesStatisticsHtml"></div>
    </div>
    <div class="half left data-widget">
        <form name="purchaseStatisticsForm" data-fun="purchaseStatistics" data-cla="purchaseReportForm"><span class="title-card">采购统计</span>{$searchTxt}</form>
        <div class="data-box-show" id="purchaseStatisticsHtml"></div>
    </div>
    <div class="half left data-widget">
        <form name="stockAgeForm" data-fun="stockAge" data-cla="inventoryReportForm"><span class="title-card">库龄分布</span>{$searchTxt}</form>
        <div class="data-box-show" id="stockAgeHtml"></div>
    </div>
</div>
{$this->flowChart('container', 'erpData')}
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<script>
function search_line(form,cla,fun) {
     $("#" + fun + "Html").html("数据查询中，请稍后。。。");
     //串联表单
        var formName = form.split(",");
        var serialize = "";
        var a = "";
        for (var i = 0; i < formName.length; i++) {
            if (serialize == "") {
                a = "";
            } else {
                a = "&";
            }
            if (formName[i] != "") {
                serialize += a + $("[name=" + formName[i] + "]").serialize();
            }
        }
    $.post(root + "control/adIndex.html?cla=" + cla + "&fun=" + fun, serialize, function (data) {
         $("#" + fun + "Html").html(data.html);
    }, "json");
}

/**
* 看板搜索
*/
function cardSearch(obj){
    let searchform = $(obj).parents("form");
    let formName = searchform.attr('name');
    let fun = searchform.data('fun');
    let cla = searchform.data('cla');
    search_line(formName,cla, fun)
}

$(function() {
    search_line('boardHomeForm','salesReportForm', 'boardHome')
    search_line('salesStatisticsForm','salesReportForm','salesStatistics');
    search_line('purchaseStatisticsForm','purchaseReportForm','purchaseStatistics')
    search_line('stockAgeForm','inventoryReportForm','stockAge')
})
</script>
eof;
    }

    /** 生成节点数据
     *
     * @param array $data
     * @return array
     */
    public function nodeData(array $data): array
    {
        $page = isset($data['page']) ? $data['page'] : '';
        if ($page) {
            $name = isset($data['name']) ? $data['name'] : '';
            $file = isset($data['file']) ? $data['file'] : 'client';
            return [
                'type'  => 'node',
                'id'    => $page,
                'x'     => isset($data['x']) ? $data['x'] : '',
                'y'     => isset($data['y']) ? $data['y'] : '',
                'name'  => $name,
                'title' => isset($data['title']) ? $data['title'] : $name,
                'power' => $this->power($page, 'see'),
                'img'   => root . 'img/flowChart/' . $file . '/' . ($this->power($page, 'see') ? $page : $page . '_noauth') . '.svg',
                'url'   => root . "control/adIndex.html?cla={$page}&fun=home",
            ];
        } else {
            return [];
        }
    }

    public function erpData(): bool|string
    {
        $json['result'] = [
            /**********销售********/
            [
                'type'   => 'group',
                'id'     => 'saleGroup',
                'name'   => '',
                'x'      => 30,
                'y'      => 75,
                'width'  => 270,
                'height' => 600,
            ],
            $this->nodeData(['page' => 'orderStore', 'x' => 55, 'y' => 100, 'name' => '订货订单', 'file' => 'erp']),
            $this->nodeData(['page' => 'salesContract', 'x' => 205, 'y' => 100, 'name' => '销售合同', 'file' => 'erp']),
            $this->nodeData(['page' => 'saleOrder', 'x' => 130, 'y' => 250, 'name' => '销售订单', 'file' => 'erp']),
            $this->nodeData(['page' => 'saleSendOrder', 'x' => 55, 'y' => 400, 'name' => '销售发货单', 'file' => 'erp']),
            $this->nodeData(['page' => 'saleRefundOrder', 'x' => 205, 'y' => 400, 'name' => '销售退货单', 'file' => 'erp']),
            $this->nodeData(['page' => 'saleInvoice', 'x' => 130, 'y' => 550, 'name' => '销售发票', 'file' => 'erp']),
            /**********生产制造********/
            [
                'type'   => 'group',
                'id'     => 'produceGroup',
                'name'   => '生产制造',
                'x'      => 380,
                'y'      => 75,
                'width'  => 150,
                'height' => 120,
            ],
            /**********售后********/
            [
                'type'   => 'group',
                'id'     => 'afterSales',
                'name'   => '',
                'x'      => 380,
                'y'      => 240,
                'width'  => 150,
                'height' => 120,
            ],
            $this->nodeData(['page' => 'aftermarketRegister', 'x' => 420, 'y' => 260, 'name' => '售后登记', 'title' => '维修登记', 'file' => 'erp']),
            /**********物流********/
            [
                'type'   => 'group',
                'id'     => 'logistics',
                'name'   => '',
                'x'      => 380,
                'y'      => 405,
                'width'  => 150,
                'height' => 270,
            ],
            $this->nodeData(['page' => 'logisticsCar', 'x' => 420, 'y' => 420, 'name' => '车辆管理', 'title' => '内部车辆', 'file' => 'erp']),
            $this->nodeData(['page' => 'deliveryManage', 'x' => 420, 'y' => 550, 'name' => '发货管理', 'file' => 'erp']),
            /**********采购********/
            [
                'type'   => 'group',
                'id'     => 'purchase',
                'name'   => '',
                'x'      => 625,
                'y'      => 75,
                'width'  => 270,
                'height' => 600,
            ],
            $this->nodeData(['page' => 'purchaseApply', 'x' => 660, 'y' => 100, 'name' => '采购申请', 'title' => '订货订单', 'file' => 'erp']),
            $this->nodeData(['page' => 'purchaseContract', 'x' => 810, 'y' => 100, 'name' => '采购合同', 'file' => 'erp']),
            $this->nodeData(['page' => 'purchaseOrder', 'x' => 735, 'y' => 250, 'name' => '采购订单', 'file' => 'erp']),
            $this->nodeData(['page' => 'purchaseGetOrder', 'x' => 660, 'y' => 400, 'name' => '采购收货单', 'file' => 'erp']),
            $this->nodeData(['page' => 'purchaseRefundOrder', 'x' => 810, 'y' => 400, 'name' => '采购退货单', 'file' => 'erp']),
            $this->nodeData(['page' => 'incomeInvoice', 'x' => 735, 'y' => 550, 'name' => '采购发票', 'title' => '进项发票', 'file' => 'erp']),
            /*********委外*********/
            [
                'type'   => 'group',
                'id'     => 'outsource',
                'name'   => '',
                'x'      => 990,
                'y'      => 75,
                'width'  => 270,
                'height' => 600,
            ],
            $this->nodeData(['page' => 'outsourceContract', 'x' => 1015, 'y' => 100, 'name' => '委外合同', 'file' => 'erp']),
            $this->nodeData(['page' => 'outsourcePickRefund', 'x' => 1165, 'y' => 100, 'name' => '委外退料单', 'file' => 'erp']),
            $this->nodeData(['page' => 'outsourceProcess', 'x' => 1015, 'y' => 250, 'name' => '委外加工单', 'file' => 'erp']),
            $this->nodeData(['page' => 'outsourcePick', 'x' => 1165, 'y' => 250, 'name' => '委外发料单', 'file' => 'erp']),
            $this->nodeData(['page' => 'outsourceGet', 'x' => 1015, 'y' => 400, 'name' => '委外收货单', 'file' => 'erp']),
            $this->nodeData(['page' => 'outsourceRefund', 'x' => 1015, 'y' => 550, 'name' => '委外退货单', 'file' => 'erp']),
            $this->nodeData(['page' => 'outsourceSettle', 'x' => 1165, 'y' => 550, 'name' => '委外结算单', 'file' => 'erp']),
            /**********库存********/
            [
                'type'   => 'group',
                'id'     => 'inventoryGroup',
                'name'   => '',
                'x'      => 30,
                'y'      => 765,
                'width'  => 1230,
                'height' => 270,
            ],
            $this->nodeData(['page' => 'inStock', 'x' => 55, 'y' => 790, 'name' => '入库', 'file' => 'erp']),
            $this->nodeData(['page' => 'outStock', 'x' => 185, 'y' => 790, 'name' => '出库', 'file' => 'erp']),
            $this->nodeData(['page' => 'moveStock', 'x' => 315, 'y' => 790, 'name' => '移库', 'file' => 'erp']),
            $this->nodeData(['page' => 'inventoryAllot', 'x' => 455, 'y' => 790, 'name' => '调拨单', 'file' => 'erp']),
            $this->nodeData(['page' => 'inventory', 'x' => 595, 'y' => 790, 'name' => '盘点单', 'file' => 'erp']),
            /*$this->nodeData(['page' => 'assembly', 'x' => 595, 'y' => 790, 'name' => '组装单', 'file' => 'erp']),
            $this->nodeData(['page' => 'dismantle', 'x' => 735, 'y' => 790, 'name' => '拆解单', 'file' => 'erp']),
            $this->nodeData(['page' => 'inStockOther', 'x' => 885, 'y' => 790, 'name' => '其他入库单', 'file' => 'erp']),
            $this->nodeData(['page' => 'outStockOther', 'x' => 1035, 'y' => 790, 'name' => '其他出库单', 'file' => 'erp']),
            $this->nodeData(['page' => 'inventory', 'x' => 1170, 'y' => 790, 'name' => '盘点单', 'file' => 'erp']),*/
            $this->nodeData(['page' => 'inventoryBalance', 'x' => 535, 'y' => 930, 'name' => '库存余额表', 'file' => 'erp']),
        ];
        $json['link']   = [
            //group link
            ['source' => 'saleGroup', 'target' => 'inventoryGroup', 'vertices' => []],
            ['source' => 'saleGroup', 'target' => 'produceGroup', 'vertices' => []],
            ['source' => 'saleGroup', 'target' => 'afterSales', 'vertices' => []],
            ['source' => 'saleGroup', 'target' => 'logistics', 'vertices' => []],
            ['source' => 'produceGroup', 'target' => 'purchase', 'vertices' => []],
            ['source' => 'produceGroup', 'target' => 'outsource', 'vertices' => [['x' => 455, 'y' => 40], ['x' => 1140, 'y' => 40]]],
            ['source' => 'logistics', 'target' => 'inventoryGroup', 'vertices' => []],
            ['source' => 'purchase', 'target' => 'inventoryGroup', 'vertices' => [['x' => 760, 'y' => 675]]],
            ['source' => 'outsource', 'target' => 'inventoryGroup', 'vertices' => []],
            //node link
            //销售
            ['source' => 'orderStore', 'target' => 'saleOrder', 'vertices' => [['x' => 90, 'y' => 290]]],
            ['source' => 'salesContract', 'target' => 'saleOrder', 'vertices' => [['x' => 240, 'y' => 290]]],
            ['source' => 'saleOrder', 'target' => 'saleSendOrder', 'vertices' => [['x' => 165, 'y' => 360], ['x' => 90, 'y' => 360]]],
            ['source' => 'saleSendOrder', 'target' => 'saleInvoice', 'vertices' => [['x' => 90, 'y' => 510], ['x' => 165, 'y' => 510]]],
            ['source' => 'saleRefundOrder', 'target' => 'saleInvoice', 'vertices' => [['x' => 240, 'y' => 510], ['x' => 165, 'y' => 510]]],
            ['source' => 'saleSendOrder', 'target' => 'saleRefundOrder', 'vertices' => []],
            //物流
            ['source' => 'logisticsCar', 'target' => 'deliveryManage', 'vertices' => []],
            //采购
            ['source' => 'purchaseApply', 'target' => 'purchaseOrder', 'vertices' => [['x' => 695, 'y' => 290]]],
            ['source' => 'purchaseContract', 'target' => 'purchaseOrder', 'vertices' => [['x' => 845, 'y' => 290]]],
            ['source' => 'purchaseOrder', 'target' => 'purchaseGetOrder', 'vertices' => [['x' => 770, 'y' => 360], ['x' => 695, 'y' => 360]]],
            ['source' => 'purchaseGetOrder', 'target' => 'incomeInvoice', 'vertices' => [['x' => 695, 'y' => 510], ['x' => 770, 'y' => 510]]],
            ['source' => 'purchaseRefundOrder', 'target' => 'incomeInvoice', 'vertices' => [['x' => 845, 'y' => 510], ['x' => 770, 'y' => 510]]],
            ['source' => 'purchaseGetOrder', 'target' => 'purchaseRefundOrder', 'vertices' => []],
            //委外
            ['source' => 'outsourceContract', 'target' => 'outsourceProcess', 'vertices' => []],
            ['source' => 'outsourcePick', 'target' => 'outsourcePickRefund', 'vertices' => []],
            ['source' => 'outsourceProcess', 'target' => 'outsourcePick', 'vertices' => []],
            ['source' => 'outsourceProcess', 'target' => 'outsourceGet', 'vertices' => []],
            ['source' => 'outsourceGet', 'target' => 'outsourceRefund', 'vertices' => []],
            ['source' => 'outsourceRefund', 'target' => 'outsourceSettle', 'vertices' => []],
            ['source' => 'outsourcePick', 'target' => 'outsourceSettle', 'vertices' => []],
            ['source' => 'outsourceGet', 'target' => 'outsourceSettle', 'vertices' => [['x' => 1200, 'y' => 440]]],
            //库存
            ['source' => 'inventoryAllot', 'target' => 'inventoryBalance', 'vertices' => [['x' => 490, 'y' => 960]]],
            ['source' => 'moveStock', 'target' => 'inventoryBalance', 'vertices' => [['x' => 350, 'y' => 960]]],
            ['source' => 'outStock', 'target' => 'inventoryBalance', 'vertices' => [['x' => 220, 'y' => 960]]],
            ['source' => 'inStock', 'target' => 'inventoryBalance', 'vertices' => [['x' => 90, 'y' => 960]]],

            /*['source' => 'assembly', 'target' => 'inventoryBalance', 'vertices' => [['x' => 630, 'y' => 960]]],
            ['source' => 'dismantle', 'target' => 'inventoryBalance', 'vertices' => [['x' => 770, 'y' => 960]]],
            ['source' => 'inStockOther', 'target' => 'inventoryBalance', 'vertices' => [['x' => 920, 'y' => 960]]],
            ['source' => 'outStockOther', 'target' => 'inventoryBalance', 'vertices' => [['x' => 1070, 'y' => 960]]],*/
        ];
        return json_encode($json, 320);
    }

    /**
     * 生产制造主页
     */
    private function produceHomePage(): string
    {
        // 搜索文本框
        $searchTxt =
            self::searchText([
                'click'   => "cardSearch(this)",
                'search'  => true,
                "name"    => "date",
                "title"   => "时间段",
                "class"   => "line28 width200",
                "value"   => date('Y-m-01', time()) . ' ~ ' . date('Y-m-t', time()),
                'laydate' => ['range' => '~', 'type' => 'date'],
            ]);
        return <<<eof
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<div class="home-warp">
    <div class="left-box">
        <div class="chart-widget">
            <p class="chart-title">业务流程图</p>
            <div id="container" class="canvas"></div>
        </div>
    </div>
    <div class="right-box">
        <div class="data-widget">
            {$this->backlog()}
        </div>
        <div style="overflow: hidden">
            <div class="data-widget">
                {$this->alertMessage()}
            </div>
        </div>
    </div>
    <div class="data-widget left m-t-0" style="width: 96.6%;">
        <form name="boardProduceForm" data-fun="boardProduce" data-cla="homepage"><span class="title-card">数据看板</span>{$searchTxt}</form>
        <ul class="revenue" id="boardProduceHtml">
            <li class="quarter left vertical-line">
                <div class="title-card-li-content">
                   <div>产值</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                <div class="title-card-li-content">
                   <div>材料</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                 <div class="title-card-li-content">
                   <div>人工</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
             <div class="title-card-li-content">
                   <div>分摊费用</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
        </ul>
    </div>
    <div class="data-widget left" style="width: 96.6%;">
        <form name="outputValueStatisticsForm" data-fun="outputValueStatistics" data-cla="homepage"><span class="title-card">产值统计</span>{$searchTxt}</form>
        <div class="data-box-show" id="outputValueStatisticsHtml"></div>
    </div>
    <div class="half left data-widget">
        <form name="materialConsumptionForm" data-fun="materialConsumption" data-cla="homepage"><span class="title-card">材料耗用</span>{$searchTxt}</form>
        <div class="data-box-show" id="materialConsumptionHtml"></div>
    </div>
    <div class="half left data-widget">
        <form name="wageForm" data-fun="wage" data-cla="homepage"><span class="title-card">计时计件工资</span>{$searchTxt}</form>
        <div class="data-box-show" id="wageHtml"></div>
    </div>
</div>
{$this->flowChart('container', 'produceData')}
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<script>
function search_line(form,cla,fun) {
     $("#" + fun + "Html").html("数据查询中，请稍后。。。");
     //串联表单
        var formName = form.split(",");
        var serialize = "";
        var a = "";
        for (var i = 0; i < formName.length; i++) {
            if (serialize == "") {
                a = "";
            } else {
                a = "&";
            }
            if (formName[i] != "") {
                serialize += a + $("[name=" + formName[i] + "]").serialize();
            }
        }
    $.post(root + "control/adIndex.html?cla=" + cla + "&fun=" + fun, serialize, function (data) {
         $("#" + fun + "Html").html(data.html);
    }, "json");
}

/**
* 看板搜索
*/
function cardSearch(obj){
    let searchform = $(obj).parents("form");
    let formName = searchform.attr('name');
    let fun = searchform.data('fun');
    let cla = searchform.data('cla');
    search_line(formName,cla, fun)
}

$(function() {
    search_line('boardProduceForm','homepage', 'boardProduce')
    search_line('outputValueStatisticsForm','homepage','outputValueStatistics');
    search_line('materialConsumptionForm','homepage','materialConsumption')
    search_line('wageForm','homepage','wage')
})
</script>
eof;
    }

    /**
     * 桌面数据看板
     */
    public function boardProduce(): bool|string
    {
        $output_value_tip = componentClass::tipComponent('产值=产量*销售基准价（不含税）', '?');
        $material_fee_tip = componentClass::tipComponent('材料=材料耗用数量*出库成本', '?');
        $people_fee_tip   = componentClass::tipComponent('人工=计时工资+计件工资', '?');
        $date             = $this->post('date');
        $where            = " and a.coid = '" . self::$coid . "' and a.state = '已确认' ";
        if ($date) {
            $where .= self::timeComparison($date, field: 'a.recordDate');
        }
        $outputValue    = 0; //产值
        $materialFee    = 0; //材料
        $peopleFee      = 0; //人工
        $costSharing    = 0; //分摊费用
        $costCountClass = new costCountClass();
        $result         = find(array(
            "table" => "machining_order_mx as mx join machining_order as a on a.id = mx.orderId",
            "field" => "a.*,mx.id as mxId,mx.materialId",
            "where" => " 1 " . $where . " order by a.recordDate desc,a.time desc"
        ));
        if (is_array($result['array'])) {
            foreach ($result['array'] as $array) {
                $material    = query("material", " id = '$array[materialId]' ", "salePrice");
                $result      = $costCountClass->inFee($array['mxId']);
                $peopleFee   += $costCountClass->peopleFee($array['mxId']);
                $materialFee += $costCountClass->materialFee($array['mxId']);
                $outputValue += $result['num'] * $material['salePrice'];
                $costSharing += $result['money'];
            }
        }
        $json['html'] = '';
        //产值
        $text         = $outputValue > 10000 ? '万' : '';
        $money        = round($outputValue > 10000 ? ($outputValue / 10000) : $outputValue, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                               <div>产值{$output_value_tip}</div>
                                <div><span class="title-card-li-money">￥{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //材料
        $text         = $materialFee > 10000 ? '万' : '';
        $money        = $materialFee > 10000 ? round(($materialFee / 10000), 2) : round($materialFee, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                                <div>材料{$material_fee_tip}</div>
                                <div><span class="title-card-li-money">￥{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //人工
        $text         = $peopleFee > 10000 ? '万' : '';
        $money        = round($peopleFee > 10000 ? ($peopleFee / 10000) : $peopleFee, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                               <div>人工{$people_fee_tip}</div>
                                <div><span class="title-card-li-money">￥{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;
        //分摊费用
        $text         = $costSharing > 10000 ? '万' : '';
        $money        = round($costSharing > 10000 ? ($costSharing / 10000) : $costSharing, 2);
        $json['html'] .= <<<efo
                        <li class="quarter left vertical-line">
                            <div class="title-card-li-content">
                                <div>分摊费用</div>
                                <div><span class="title-card-li-money">{$money}</span><span>{$text}</span></div>
                            </div>
                        </li>
         
efo;

        return json_encode($json, 320);
    }

    /**
     * 产值统计
     *
     * @return bool|string
     */
    public function outputValueStatistics(): bool|string
    {
        $date = $this->post('date');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m-d', strtotime("-14 day"));
            $timeArr[1] = $this->date;
        }
        //时间段数组
        $dateArr = [];
        $m       = $timeArr[0];
        while ($m <= $timeArr[1]) {
            $dateArr[] = ['name' => date("m月d日", strtotime($m)), 'date' => $m];
            $m         = date("Y-m-d", strtotime($m . " +1 day"));
        }

        $costCountClass = new costCountClass();
        //车间
        $product_line = find(array(
            "table" => "product_line",
            "field" => "workshop",
            "where" => " coid = '" . self::$coid . "' and state = '启用' group by workshop "
        ));
        $series       = [];
        foreach ((array)$product_line['array'] as $array) {
            $res = [];
            foreach ((array)$dateArr as $val) {
                $where       = " and a.coid = '" . self::$coid . "' and a.state = '已确认' and a.recordDate = '$val[date]' and a.lineId in (select id from product_line where workshop = '$array[workshop]') ";
                $outputValue = 0; //产值
                $result      = find(array(
                    "table" => "machining_order as a join machining_order_mx as mx on a.id = mx.orderId",
                    "field" => "a.*,mx.id as mxId,mx.materialId",
                    "where" => " 1 " . $where . " order by a.recordDate desc,a.time desc"
                ));

                if (is_array($result['array'])) {
                    foreach ($result['array'] as $arr) {
                        $material    = query("material", " id = '$arr[materialId]' ", "salePrice");
                        $result      = $costCountClass->inFee($arr['mxId']);
                        $outputValue += $result['num'] * $material['salePrice'];
                    }
                }
                $res[] = round($outputValue / 10000, 2);
            }
            //每个车间产值
            $series[] = [
                'name'     => $array['workshop'],
                'stack'    => 'value',
                'emphasis' => json_encode(['focus' => 'series']),
                'data'     => $res,
            ];
        }
        $data         = [
            "subtext" => '单位：万元',
            "name"    => array_column($dateArr, 'name'),
            "series"  => $series,
        ];
        $json['html'] = $this->curve($data, 'bar');
        return json_encode($json, 320);
    }

    /**
     * 材料耗用
     *
     * @return bool|string
     */
    public function materialConsumption(): bool|string
    {
        $date = $this->post('date');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m-d', strtotime("-14 day"));
            $timeArr[1] = $this->date;
        }
        $m   = $timeArr[0];
        $res = [];
        while ($m <= $timeArr[1]) {
            $result   = find(array(
                "table" => "machining_order_detail as a join machining_order as b on a.orderId = b.id join material as c on c.id = a.materialId",
                "field" => "a.*,b.orderNo,date(b.time) as recordDate,b.lineId,b.type,c.code,c.name as materialName,c.model",
                "where" => " a.coid = '" . self::$coid . "' and b.state = '已确认' and b.recordDate = '$m' "
            ));
            $standard = 0;
            $actual   = 0;
            foreach ((array)$result['array'] as $array) {
                $material = query('material', "id = '$array[materialId]'", 'buyPrice');
                //领料
                $pickNum      = 0;
                $pickOrderAll = find(array(
                    'table' => 'pick_order as a join pick_order_detail as b on a.id = b.orderId',
                    "where" => "a.state = '已确认' and a.type=0 and b.sourceId = '$array[id]' and b.materialId = '$array[materialId]'"
                ));
                foreach ($pickOrderAll['array'] as $val) {
                    $inventoryAll = find(array(
                        'table' => 'inventory_detail',
                        'where' => "sourceId = '$val[id]' and num >0 and coid = '" . self::$coid . "'"
                    ));
                    foreach ($inventoryAll['array'] as $item) {
                        $pickNum += machiningOrderClass::material_num_change($array['materialId'], $item['unit'], $array['unit'], $item['num']);
                    }
                }
                $pickNum = round($pickNum, 2);
                //退料
                $refundNum      = 0;
                $refundOrderAll = find(array(
                    'table' => 'pick_order as a join pick_order_detail as b on a.id = b.orderId',
                    "where" => "a.state = '已确认' and a.type=1 and b.sourceId = '$array[id]' and b.materialId = '$array[materialId]'"
                ));
                foreach ($refundOrderAll['array'] as $val) {
                    $inventoryAll = find(array(
                        'table' => 'inventory_detail',
                        'where' => "sourceId = '$val[id]' and num >0 and coid = '" . self::$coid . "'"
                    ));
                    foreach ($inventoryAll['array'] as $item) {
                        $refundNum += machiningOrderClass::material_num_change($array['materialId'], $item['unit'], $array['unit'], $item['num']);
                    }
                }
                $refundOrderAll = find(array(
                    'table' => 'pick_order as a join pick_order_detail as b on a.id = b.orderId',
                    "where" => "a.state = '已确认' and a.type=1 and b.sourceId in (select id from pick_order_detail where sourceId = '$array[id]') and b.materialId = '$array[materialId]'"
                ));
                foreach ($refundOrderAll['array'] as $val) {
                    $refundNum += machiningOrderClass::material_num_change($array['materialId'], $val['unit'], $array['unit'], $val['num']);
                }
                $refundNum = round($refundNum, 2);

                //配料
                $disNum = 0;
                $all    = find(array(
                    'table' => 'material_distribute_num as a join material_distribute as b on a.orderId = b.id',
                    'field' => "a.*",
                    'where' => "b.state = '已确认' and a.materialId = '$array[materialId]' and machiningOrderMxId = '$array[targetSkuId]'"
                ));
                foreach ($all['array'] as $val) {
                    $disNum += machiningOrderClass::material_num_change($array['materialId'], $val['unit'], $array['unit'], $val['num']);
                }
                $standard = $array['quantity'] * $material['buyPrice'];
                $actual   = ($pickNum + $disNum - $refundNum - $array['quantity']) * $material['buyPrice'];
            }
            $res[] = [
                'date'     => date("m月d日", strtotime($m)),
                'standard' => round($standard / 10000, 2),
                'actual'   => round($actual / 10000, 2),
            ];
            $m     = date("Y-m-d", strtotime($m . " +1 day"));
        }
        $data         = [
            "subtext" => '单位：万元',
            "name"    => array_column($res, 'date'),
            "series"  => [
                [
                    'name' => '标准用量',
                    'data' => array_column($res, 'standard'),
                ],
                [
                    'name' => '实际耗用',
                    'data' => array_column($res, 'actual'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data, 'area');
        return json_encode($json, 320);
    }

    /**
     * 计时计件工资 - 返回数据
     */
    public function wage(): bool|string
    {
        $date = $this->post('date');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m-d', strtotime("-14 day"));
            $timeArr[1] = $this->date;
        }

        $arr = find(array("table" => "team", "field" => "id,name", "where" => " coid = '" . self::$coid . "' and state = '启用' "));
        $res = [];
        foreach ((array)$arr['array'] as $index => $val) {
            $pieceMoney = 0;
            $timeMoney  = 0;
            //计件工资
            $result_piece = find(array(
                "table" => "process_report_staff as a join process_report as b on a.orderId = b.id join machining_send_order as ma on ma.id = b.sendId",
                "field" => "b.*,a.stid as teamStid,ma.unit as fromUnit,ma.machiningOrderMxId,ma.orderNo as sendNo",
                "where" => " b.classify = '工序报工' and b.coid = '" . self::$coid . "' and b.state = '已确认' and b.teamId = '$val[id]' and teamNo >= '$timeArr[0]' and teamNo <= '$timeArr[1]' "
            ));
            foreach ((array)$result_piece['array'] as $array) {
                $material        = query('material', "id = '$array[materialId]'");
                $routMx          = query('routing_detail', "id = '$array[routingMxId]'");
                $routMx['price'] = $routMx['price'] ?: 0;
                $array['yield']  = machiningOrderClass::material_num_change($array['materialId'], $array['fromUnit'], $material['unit'], $array['yield']);
                $pieceMoney      += $routMx['price'] * $array['yield'];
            }
            //计时工资
            $result_time = find(array(
                "table" => "timing_report",
                "field" => "distinct recordDate,teamId,staffId",
                "where" => " coid = '" . self::$coid . "' and teamId = '$val[id]' and recordDate >= '$timeArr[0]' and recordDate <= '$timeArr[1]' "
            ));
            foreach ((array)$result_time['array'] as $array) {
                $hour      = find(array(
                    'table' => 'timing_report',
                    'where' => "recordDate = '$array[recordDate]' and teamId = '$array[teamId]' and staffId = '$array[staffId]' and coid = '" . self::$coid . "'",
                    'sum'   => "hour"
                ));
                $teamMx    = query('team_detail', "orderId = '$array[teamId]' and stid = '$array[staffId]'");
                $timeMoney += $hour * $teamMx['price'];
            }
            $res[] = [
                'text'       => $val['name'],
                'pieceMoney' => round($pieceMoney / 10000, 2),
                'timeMoney'  => round($timeMoney / 10000, 2),
            ];
        }
        $data         = [
            "subtext" => '单位：万元',
            "name"    => array_column($res, 'text'),
            "series"  => [
                [
                    'name' => '计件工资',
                    'data' => array_column($res, 'pieceMoney'),
                ],
                [
                    'name' => '计时工资',
                    'data' => array_column($res, 'timeMoney'),
                ],
            ],
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }

    public function produceData(): bool|string
    {
        $json['result'] = [
            /**********左侧********/
            [
                'type'   => 'group',
                'id'     => 'letfGroup',
                'name'   => '',
                'x'      => 50,
                'y'      => 75,
                'width'  => 750,
                'height' => 750,
            ],
            $this->nodeData(['page' => 'saleOrder', 'x' => 75, 'y' => 400, 'name' => '销售订单', 'file' => 'produce']),
            $this->nodeData(['page' => 'machiningOrder', 'x' => 225, 'y' => 400, 'name' => '生产计划', 'file' => 'produce']),
            $this->nodeData(['page' => 'semiMachiningOrder', 'x' => 375, 'y' => 400, 'name' => '半成品加工单', 'file' => 'produce']),
            $this->nodeData(['page' => 'workshopClock', 'x' => 525, 'y' => 400, 'name' => '车间考勤表', 'file' => 'produce']),
            $this->nodeData(['page' => 'pieceCount', 'x' => 675, 'y' => 400, 'name' => '计件工资', 'file' => 'produce']),
            $this->nodeData(['page' => 'outsourceSendOrder', 'x' => 375, 'y' => 100, 'name' => '委外派工单', 'file' => 'produce']),
            $this->nodeData(['page' => 'machiningSendOrder', 'x' => 375, 'y' => 250, 'name' => '生产派工单', 'file' => 'produce']),
            $this->nodeData(['page' => 'pickOrder', 'x' => 375, 'y' => 550, 'name' => '领料单', 'file' => 'produce']),
            $this->nodeData(['page' => 'ingredientsOrder', 'x' => 375, 'y' => 700, 'name' => '配料单', 'file' => 'produce']),
            $this->nodeData(['page' => 'outProcessReport', 'x' => 525, 'y' => 100, 'name' => '委外报工单', 'title' => '委外报工', 'file' => 'produce']),
            $this->nodeData(['page' => 'processReport', 'x' => 525, 'y' => 250, 'name' => '生产报工单', 'title' => '工序报工', 'file' => 'produce']),
            $this->nodeData(['page' => 'refundMaterialOrder', 'x' => 525, 'y' => 550, 'name' => '退料单', 'file' => 'produce']),
            $this->nodeData(['page' => 'tempInventory', 'x' => 525, 'y' => 700, 'name' => '线边库存', 'file' => 'produce']),
            $this->nodeData(['page' => 'scrappedOrder', 'x' => 675, 'y' => 100, 'name' => '报废申请单', 'file' => 'produce']),
            $this->nodeData(['page' => 'machiningInOrder', 'x' => 675, 'y' => 250, 'name' => '生产入库单', 'file' => 'produce']),
            $this->nodeData(['page' => 'materialDistribute', 'x' => 675, 'y' => 700, 'name' => '材料倒冲', 'file' => 'produce']),
            /**********右侧********/
            [
                'type'   => 'group',
                'id'     => 'rightUpGroup',
                'name'   => '',
                'x'      => 920,
                'y'      => 75,
                'width'  => 270,
                'height' => 270,
            ],
            [
                'type'   => 'group',
                'id'     => 'rightDownGroup',
                'name'   => '',
                'x'      => 920,
                'y'      => 390,
                'width'  => 270,
                'height' => 430,
            ],
            $this->nodeData(['page' => 'processingInspection', 'x' => 945, 'y' => 100, 'name' => '制程检验', 'file' => 'produce']),
            $this->nodeData(['page' => 'materialInspection', 'x' => 945, 'y' => 250, 'name' => '来料检验', 'file' => 'produce']),
            $this->nodeData(['page' => 'equipment', 'x' => 945, 'y' => 400, 'name' => '设备', 'file' => 'produce']),
            $this->nodeData(['page' => 'parts', 'x' => 945, 'y' => 550, 'name' => '配件', 'file' => 'produce']),
            $this->nodeData(['page' => 'mold', 'x' => 945, 'y' => 700, 'name' => '模具', 'file' => 'produce']),
            $this->nodeData(['page' => 'processSpotCheck', 'x' => 1095, 'y' => 100, 'name' => '工序巡检', 'file' => 'produce']),
            $this->nodeData(['page' => 'outsourceInspection', 'x' => 1095, 'y' => 250, 'name' => '委外检验', 'title' => '委外入库检验', 'file' => 'produce']),
            $this->nodeData(['page' => 'equipmentInspection', 'x' => 1095, 'y' => 400, 'name' => '巡检', 'file' => 'produce']),
            $this->nodeData(['page' => 'equipmentMaintenance', 'x' => 1095, 'y' => 550, 'name' => '保养', 'file' => 'produce']),
            $this->nodeData(['page' => 'equipmentRepair', 'x' => 1095, 'y' => 700, 'name' => '维修', 'file' => 'produce']),
        ];
        $json['link']   = [
            //group link
            //node link
            ['source' => 'saleOrder', 'target' => 'machiningOrder', 'vertices' => []],
            ['source' => 'machiningOrder', 'target' => 'semiMachiningOrder', 'vertices' => []],
            ['source' => 'semiMachiningOrder', 'target' => 'pickOrder', 'vertices' => []],
            ['source' => 'semiMachiningOrder', 'target' => 'machiningSendOrder', 'vertices' => []],
            ['source' => 'machiningSendOrder', 'target' => 'outsourceSendOrder', 'vertices' => []],
            ['source' => 'machiningOrder', 'target' => 'outsourceSendOrder', 'vertices' => [['x' => 260, 'y' => 140]]],
            ['source' => 'machiningOrder', 'target' => 'machiningSendOrder', 'vertices' => [['x' => 260, 'y' => 290]]],
            ['source' => 'machiningOrder', 'target' => 'pickOrder', 'vertices' => [['x' => 260, 'y' => 590]]],
            ['source' => 'machiningOrder', 'target' => 'ingredientsOrder', 'vertices' => [['x' => 260, 'y' => 740]]],
            ['source' => 'outsourceSendOrder', 'target' => 'outProcessReport', 'vertices' => []],
            ['source' => 'outProcessReport', 'target' => 'processReport', 'vertices' => []],
            ['source' => 'processReport', 'target' => 'machiningInOrder', 'vertices' => []],
            ['source' => 'machiningInOrder', 'target' => 'scrappedOrder', 'vertices' => []],
            ['source' => 'machiningSendOrder', 'target' => 'processReport', 'vertices' => []],
            ['source' => 'processReport', 'target' => 'workshopClock', 'vertices' => []],
            ['source' => 'workshopClock', 'target' => 'pieceCount', 'vertices' => []],
            ['source' => 'pickOrder', 'target' => 'refundMaterialOrder', 'vertices' => []],
            ['source' => 'refundMaterialOrder', 'target' => 'tempInventory', 'vertices' => []],
            ['source' => 'ingredientsOrder', 'target' => 'tempInventory', 'vertices' => []],
            ['source' => 'tempInventory', 'target' => 'materialDistribute', 'vertices' => []],
        ];
        return json_encode($json, 320);
    }

    private function style(): string
    {
        return <<<eof
<style>
.chart-title{font-size: 14px;font-weight: 700;padding: 0 10px;}
::-webkit-scrollbar-corner {background-color: #fff;}
.m-t-0 {margin: 0 5px 5px 5px!important;}
.chart-widget{background-color: #fff;padding: 8px 5px;margin: 5px 5px;min-height: 180px;overflow-y: auto;}

.title-card-li-content{
  text-align: center;padding-top: 50px
}
.title-card-li-money{
  font-size: 28px;font-weight: bold
}
/*#body{background-color:#f2f2f2;padding:0 10px}*/
.right-box-ul{
    height: 500px;
    max-height: none;
}
 .right-box-title{
    display: flex;
 }
 .right-text{
    height: auto;
 }
 .right-box-title li{
    float: left;margin: 5px 10px;min-width: 70px;text-align: center;
 }
 .data-widget-select{
    margin-right: 10px;
 }
 .data-widget-select .fs-label{
     height: 15px;line-height: 15px;
 }
 .data-widget-select .fs-label-wrap{
     border-radius: 4px;
 }
 .aim-rank li{
    margin: 5px 0;
 }
 .aim-rank .right-box-title li:nth-child(1){min-width: 40px}
 .aim-rank .right-box-title li:nth-child(2){min-width: 50px}
 .aim-rank .right-box-title li:nth-child(3){min-width: 100px}
 .aim-rank .right-box-title li:nth-child(4){min-width: 100px}
</style>
eof;
    }

    /**
     * 客户管理主页
     */
    private function clientHomePage(): string
    {
        // 搜索文本框
        $searchTxt         = self::searchText(array('name' => 'staffName', 'click' => "cardSearch()", 'title' => '员工', 'search' => true)) .
            hidden(array('name' => 'stid', 'value' => '')) .
            self::searchText([
                'click'   => "cardSearch()",
                'search'  => true,
                "name"    => "month",
                "title"   => "时间段",
                "class"   => "line28",
                "value"   => date('Y-m'),
                'laydate' => ['type' => 'month'],
            ]);
        $record            = query('user_setting', "stid = '" . self::$stid . "' and type = '销售业绩统计'");
        $setting           = (array)json_decode($record['value'], true);
        $board             = in_array('board', $setting) ? 'display:block;' : 'display:none;';
        $performance_goals = in_array('performance_goals', $setting) ? 'display:block;' : 'display:none;';
        $payment           = in_array('payment', $setting) ? 'display:block;' : 'display:none;';
        $contract_money    = in_array('contract_money', $setting) ? 'display:block;' : 'display:none;';
        $kpi_analysis      = in_array('kpi_analysis', $setting) ? 'display:block;' : 'display:none;';
        $losing_analysis   = in_array('losing_analysis', $setting) ? 'display:block;' : 'display:none;';
        $salesPerformance  = new salesPerformanceStatisticsClass();
        return <<<eof
<div class="home-warp">
    <div class="left-box">
        <div class="chart-widget">
            <p class="chart-title">业务流程图</p>
            <div id="container" class="canvas"></div>
        </div>
    </div>
    <div class="right-box">
        <div class="data-widget">
            {$this->backlog()}
        </div>
        <div style="overflow: hidden">
            <div class="data-widget">
                {$this->message()}
            </div>
        </div>
    </div>
    <div class="data-widget left m-t-0" style="width: 96.6%;{$board}">
        <form name="data-card"><span class="title-card">数据看板</span>{$searchTxt}</form>
        <ul class="revenue">
            <li class="quarter left vertical-line">
                <div class="title-card-li-content" id="contractMoneyHtml">
                   <div>合同金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                <div class="title-card-li-content" id="backMoneyHtml">
                   <div>回款金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
                 <div class="title-card-li-content" id="remindMoneyHtml">
                   <div>剩余应收金额</div>
                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                </div>
            </li>
            <li class="quarter left vertical-line">
             <div class="title-card-li-content" id="completeRateHtml">
                   <div>目标完成率</div>
                   <div><span class="title-card-li-money">0%</span><span></span></div>
                </div>
            </li>
        </ul>
    </div>
    <div class="data-widget left" style="width: 96.6%;{$performance_goals}">
        {$salesPerformance->dataBoard(['title' => '业绩目标完成情况', 'fun' => 'targetAim', 'startDate' => date('Y-m', strtotime("-12 month")), 'endDate' => date('Y-m')])}
    </div>
    <div class="half left data-widget" style="{$payment}">
       {$salesPerformance->dataBoard(['title' => '计划回款与实际回款', 'fun' => 'planAndFact', 'startDate' => date('Y-m', strtotime("-12 month")), 'endDate' => date('Y-m')])}
    </div>
    <div class="half left data-widget" style="{$contract_money}">
        {$salesPerformance->dataBoard(['title' => '商机金额与合同金额', 'fun' => 'contractAndOpportunity', 'startDate' => date('Y-m', strtotime("-12 month")), 'endDate' => date('Y-m')])}
    </div>
    <div class="half left data-widget" style="{$kpi_analysis}">
        {$salesPerformance->dataBoard(['title' => '关键指标分布', 'fun' => 'kpiData'])}
    </div>
    <div class="half left data-widget" style="{$losing_analysis}">
        {$salesPerformance->dataBoard(['title' => '输单原因分析', 'fun' => 'loseAnalysis'])}
    </div>
</div>
{$this->flowChart('container', 'clientData')}
<script src='{$this->root}static/javascript/echarts.min.js'></script>
<script>
function search_line(formName,cla,fun) {
     $("#" + fun + "Html").html("数据查询中，请稍后。。。");
    $.post(root + "control/adIndex.html?cla=salesPerformanceStatistics&fun=" + fun, $("[name='" + formName + "']").serialize(), function (data) {
         $("#" + fun + "Html").html(data.html);
    }, "json");
}


/**
* 看板搜索
*/
function cardSearch(){
      ['contractMoney', 'backMoney', 'remindMoney', 'completeRate'].forEach((fun)=>{
                    search_line('data-card','salesPerformanceStatistics', fun)
    })
}

$(function() {
    ['contractMoney', 'backMoney', 'remindMoney', 'completeRate'].forEach((fun)=>{
                    search_line('data-card','salesPerformanceStatistics', fun)
    });
    search_line('aimRankForm','salesPerformanceStatistics','aimRank');
    search_line('signRankForm','salesPerformanceStatistics','signRank')
    $("[name='staffName']").each(function (){
          $(this).bigAutocomplete({
            url:root + 'control/adIndex.html?cla=component&fun=getStaff',
            callback:function(data,e){
                console.log(data.id);
                e.parent().siblings("input[name='stid']").val(data.id)
        }})
    })
})
</script>
eof;
    }

    /**
     * 商机金额与合同金额
     *
     * @return string
     */
    public function opportunity(): string
    {
        $months = $this->post('months');
        if (!empty($months)) {
            $timeArr = explode(' ~ ', $months);
        } else {
            $timeArr[0] = date('Y-m', strtotime("-11 month"));
            $timeArr[1] = date('Y-m');
        }
        $staffId        = $this->post('staffId');
        $opportunityAnd = $contractAnd = "";
        if ($staffId) {
            $opportunityAnd .= " and manager = '$staffId' ";
            $contractAnd    = " and salesman = '$staffId' ";
        }
        $m   = $timeArr[0];
        $res = [];
        while ($m <= $timeArr[1]) {
            $res[] = [
                'month'         => $m,
                'opportunity'   => find([
                        'table'  => "opportunity",
                        'field'  => "IFNULL(sum(exSaleMoney),0) as total",
                        'single' => " 1=1 and date_format(exSignDate, '%Y-%m') = '$m' " . $opportunityAnd,
                    ])['total'] ?? 0,
                'contractMoney' => find([
                        'table'  => "sales_contract",
                        'field'  => "IFNULL(sum(money),0) as total",
                        'single' => " state = '已通过' and date_format(signedDate, '%Y-%m') = '$m' " . $contractAnd,
                    ])['total'] ?? 0,
            ];
            $m     = date("Y-m", strtotime($m . "-01 +1 month"));
        }

        $data         = [
            "name"   => array_column($res, 'month'),
            "series" => [
                [
                    'name' => '商机',
                    'data' => array_column($res, 'opportunity'),
                ],
                [
                    'name' => '合同',
                    'data' => array_column($res, 'contractMoney'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data, 'area');
        return json_encode($json, 320);
    }

    /**
     * 离职趋势 数据
     *
     * @return string
     */
    public function collectionStatus(): string
    {
        $months = $this->post('months');
        if (!empty($months)) {
            $timeArr = explode(' ~ ', $months);
        } else {
            $timeArr[0] = date('Y-m', strtotime("-11 month"));
            $timeArr[1] = date('Y-m');
        }
        $staffId    = $this->post('staffId');
        $paymentAnd = $contractAnd = "";
        if ($staffId) {
            $paymentAnd  .= " and managerId = '$staffId' ";
            $contractAnd = " and salesman = '$staffId' ";
        }
        $m   = $timeArr[0];
        $res = [];
        while ($m <= $timeArr[1]) {
            $plan   = find([
                'table'  => "sales_contract_payback",
                'field'  => "IFNULL(sum(money),0) as total",
                'single' => " orderId in (select id from sales_contract where state = '已通过' {$contractAnd}) and date_format(date, '%Y-%m') = '$m' ",
            ])['total'] ?? 0;
            $actual = find([
                'table'  => "payment",
                'field'  => "IFNULL(sum(money),0) as total",
                'single' => " state = '已通过' and classify = 2 and targetId in (select id from sales_contract where state = '已通过') and date_format(recordDate, '%Y-%m') = '$m' " . $paymentAnd,
            ])['total'] ?? 0;
            $res[]  = [
                'month'  => $m,
                'plan'   => $plan,
                'actual' => $actual,
            ];
            $m      = date("Y-m", strtotime($m . "-01 +1 month"));
        }
        $data         = [
            "name"   => array_column($res, 'month'),
            "series" => [
                [
                    'name' => '计划回款',
                    'data' => array_column($res, 'plan'),
                ],
                [
                    'name' => '实际回款',
                    'data' => array_column($res, 'actual'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data);
        return json_encode($json, 320);
    }

    /**
     * 业绩目标完成情况 - 返回数据
     */
    public function performanceCompletion(): bool|string
    {
        $months = $this->post('months');
        if (!empty($months)) {
            $timeArr = explode(' ~ ', $months);
        } else {
            $timeArr[0] = date('Y-m', strtotime("-11 month"));
            $timeArr[1] = date('Y-m');
        }
        $staffId   = $this->post('staffId');
        $targetAnd = $contractAnd = "";
        if ($staffId) {
            $targetAnd   = " and staffId like '%$staffId%' ";
            $contractAnd = " and salesman = '$staffId' ";
        }
        $m   = $timeArr[0];
        $res = [];
        while ($m <= $timeArr[1]) {
            $res[] = [
                'month'         => $m,
                'target'        => find([
                        'table'  => "performance_target",
                        'field'  => "IFNULL(sum(money),0) as total",
                        'single' => " month = '$m' " . $targetAnd,
                    ])['total'] ?? 0,
                'contractMoney' => find([
                        'table'  => "sales_contract",
                        'field'  => "IFNULL(sum(money),0) as total",
                        'single' => " state = '已通过' and date_format(signedDate, '%Y-%m') = '$m' " . $contractAnd,
                    ])['total'] ?? 0,
            ];
            $m     = date("Y-m", strtotime($m . "-01 +1 month"));
        }
        $data         = [
            "name"   => array_column($res, 'month'),
            "series" => [
                [
                    'name' => '目标',
                    'data' => array_column($res, 'target'),
                ],
                [
                    'name' => '合同金额',
                    'data' => array_column($res, 'contractMoney'),
                ],
            ],
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }


    /**
     * 客户管理数据看板
     *
     * @return string
     */
    public function contractData(): string
    {
        //总营收 = 销售收入
        $month       = $this->post('month') ?: date('Y-m') . ' ~ ' . date('Y-m');
        $staffId     = $this->post('staffId');
        $contractAnd = $paymentAnd = $targetAnd = "";
        if ($staffId) {
            $contractAnd .= " and salesman = '$staffId' ";
            $paymentAnd  .= " and managerId = '$staffId' ";
            $targetAnd   .= " and staffId like '%$staffId%' ";
        }
        $contract_money = find([
            'table'  => "sales_contract",
            'field'  => "IFNULL(sum(money),0) as total",
            'single' => " state = '已通过' " . $contractAnd . $this->timeComparison($month, 'month', 'signedDate'),
        ])['total'] ?? 0;
        $payment        = find([
            'table'  => "payment",
            'field'  => "IFNULL(sum(money),0) as total",
            'single' => " state = '已通过' and classify = 2 and targetId in (select id from sales_contract where state = '已通过') " . $paymentAnd . $this->timeComparison($month, 'month', 'recordDate'),
        ])['total'] ?? 0;
        $surplus_money  = $contract_money - $payment;
        $data           = explode('~', $month);
        $start          = trim($data[0]);
        $end            = trim(end($data));
        $target         = find([
            'table'  => "performance_target",
            'field'  => "IFNULL(sum(money),0) as total",
            'single' => " month between '$start' and '$end' " . $targetAnd,
        ])['total'] ?? 0;
        $completionRate = $target == 0 ? 0 : round($contract_money / $target * 100, 2);
        $json['html']   = <<<EOT
        <li class="quarter left vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">合同金额</p>
                <p class="hr-p f-30">$contract_money</p>
            </div>
        </li>
        <li class="quarter left vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">回款金额</p>
                <p class="hr-p f-30">$payment</p>
            </div>
        </li>
        <li class="quarter left vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">剩余应收金额</p>
                <p class="hr-p f-30">$surplus_money</p>
            </div>
        </li>
        <li class="quarter left vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">目标完成率</p>
                <p class="hr-p f-30">$completionRate%</p>
            </div>
        </li>
EOT;
        return json_encode($json, 320);
    }

    /** 业务流程图
     *
     * @param string $id
     * @param string $fun
     * @return bool|string
     */
    public function flowChart(string $id, string $fun): bool|string
    {
        return <<<eof
<script src="{$this->root}static/javascript/x6.js"></script>
<script>
 X6.Graph.registerNode(
  'org-node',
  {
    width: 70,
    height: 80,
    markup: [
      {
        tagName: 'rect',
        selector: 'body',
      },
      {
        tagName: 'image',
        selector: 'avatar',
      },
      {
        tagName: 'text',
        selector: 'name',
      },
    ],
    attrs: {
      body: {
        refWidth: '100%',
        refHeight: '100%',
        fill: 'transparent',
        stroke: 'transparent',
        strokeWidth: 1,
        rx: 10,
        ry: 10,
        pointerEvents: 'visiblePainted',
      },
      avatar: {
        width: 48,
        height: 48,
        refX: '15%',
        refY: '8%',
      },
      name: {
        refX: '50%',
        refY: '85%',
        fill: '#333',
        fontFamily: 'Courier New',
        fontSize: 14,
        textAnchor: 'middle',
        textVerticalAnchor: 'middle',
      },
    },
  },
  true,
)
X6.Graph.registerEdge(
  'org-edge',
  {
    inherit: 'edge',
    attrs: {
      line: {
        strokeWidth: 1,
        stroke: '#aaa',
        strokeDasharray: '2,3',
      },
    },
  },
  true,
)

const graph = new X6.Graph({
  height: 1062,
  container: document.getElementById('{$id}'),
  connecting: {
    anchor: 'orth',
  },
  background: {
    color: '#fff', // 设置画布背景颜色
  },
  interacting: {
    nodeMovable: false
  },
  scroller: {
    enabled: false,
    pannable: false,
  },
  mousewheel: {
    enabled: true,
    modifiers: ['ctrl', 'meta'],
  },
})
function member(item) {
  return graph.addNode({
    x:item.x,
    y:item.y,
    shape: 'org-node',
    attrs: {
        data:{
            title:item.title,
            name:item.name,
            url:item.url,
            power:item.power
        },
        avatar: {
            opacity: 0.7,
            'xlink:href': item.img,
        },
        name: {
            text: item.name,
            wordSpacing: '-10px',
            letterSpacing: 0,
        },
    },
  })
}

function groupMember(item) {
  return graph.addNode({
    x:item.x,
    y:item.y,
    width: item.width,
    height: item.height,
    zIndex: 1,
    label: item.name,
    attrs: {
        label: {
            refY: '50%'
        },
        body: {
          fill: "transparent",
          stroke: "#aaa",
          strokeDasharray: "3,2",
          strokeWidth: 1,
        }
    }
  })
}

function link(item) {
  return graph.addEdge({
    vertices: item.vertices,
    source: {
      cell: node[item.source],
    },
    target: {
      cell: node[item.target],
    },
    shape: 'org-edge',
  })
}
const node = {}
function loopData(result) {
    result.forEach((item,index)=>{
        if (item){
            if(item.type === 'node'){
                node[item.id] = member(item)
            }else{
                node[item.id] = groupMember(item)
            }
        }
    })
}
function linkData(result) {
    result.forEach((item,index)=>{
        if (item){
            link(item)
        }
    })
}
function requestData(){
    $.post(root+'control/adIndex.html?cla=homepage&fun={$fun}',{},function(res) {
        loopData(res.result);
        linkData(res.link);
        addEvent();
    },'json')
}

function addEvent(){
    graph.on('node:click', ({ e, x, y, node, view }) => {
        if (node.attrs.data.power){
            newIframe(node.attrs.data.title,node.attrs.data.url)
        }else{
            msg('您还没有此页面的查看权限','error')
        }
    })
}
requestData();

</script>
eof. $this->style();
    }

    public function clientData(): bool|string
    {
        $json['result'] = [
            $this->nodeData(['page' => 'cluePool', 'x' => 250, 'y' => 70, 'name' => '线索池', 'file' => 'client']),
            $this->nodeData(['page' => 'clue', 'x' => 400, 'y' => 70, 'name' => '线索', 'file' => 'client']),
            $this->nodeData(['page' => 'client', 'x' => 400, 'y' => 220, 'name' => '客户', 'file' => 'client']),
            $this->nodeData(['page' => 'kehuStaff', 'x' => 550, 'y' => 220, 'name' => '联系人', 'file' => 'client']),
            $this->nodeData(['page' => 'follow', 'x' => 700, 'y' => 220, 'name' => '跟进记录', 'file' => 'client']),
            $this->nodeData(['page' => 'clientPool', 'x' => 250, 'y' => 220, 'name' => '公客池', 'file' => 'client']),
            $this->nodeData(['page' => 'visitPlan', 'x' => 700, 'y' => 70, 'name' => '拜访记录', 'title' => '访客计划', 'file' => 'client']),
            $this->nodeData(['page' => 'opportunity', 'x' => 400, 'y' => 370, 'name' => '商机', 'file' => 'client']),
            $this->nodeData(['page' => 'programme', 'x' => 550, 'y' => 370, 'name' => '方案评审', 'file' => 'client']),
            $this->nodeData(['page' => 'quotations', 'x' => 700, 'y' => 370, 'name' => '报价单', 'file' => 'client']),
            $this->nodeData(['page' => 'salesContract', 'x' => 400, 'y' => 520, 'name' => '合同', 'title' => '销售合同', 'file' => 'client']),
            $this->nodeData(['page' => 'paybackRecord', 'x' => 250, 'y' => 670, 'name' => '回款记录', 'file' => 'client']),
            $this->nodeData(['page' => 'paybackPlan', 'x' => 250, 'y' => 520, 'name' => '回款计划', 'file' => 'client']),
            $this->nodeData(['page' => 'invoice', 'x' => 400, 'y' => 670, 'name' => '开票记录', 'file' => 'client']),
        ];
        $json['link']   = [
            ['source' => 'cluePool', 'target' => 'clue', 'vertices' => []],
            ['source' => 'clue', 'target' => 'client', 'vertices' => []],
            ['source' => 'client', 'target' => 'kehuStaff', 'vertices' => []],
            ['source' => 'client', 'target' => 'opportunity', 'vertices' => []],
            ['source' => 'kehuStaff', 'target' => 'follow', 'vertices' => []],
            ['source' => 'kehuStaff', 'target' => 'visitPlan', 'vertices' => [['x' => 670, 'y' => 260], ['x' => 670, 'y' => 100]]],
            ['source' => 'clientPool', 'target' => 'client', 'vertices' => []],
            ['source' => 'opportunity', 'target' => 'programme', 'vertices' => []],
            ['source' => 'opportunity', 'target' => 'salesContract', 'vertices' => []],
            ['source' => 'programme', 'target' => 'quotations', 'vertices' => []],
            ['source' => 'invoice', 'target' => 'paybackRecord', 'vertices' => []],
            ['source' => 'paybackPlan', 'target' => 'paybackRecord', 'vertices' => []],
            ['source' => 'salesContract', 'target' => 'invoice', 'vertices' => []],
            ['source' => 'salesContract', 'target' => 'paybackPlan', 'vertices' => []],
            ['source' => 'quotations', 'target' => 'salesContract', 'vertices' => [['x' => 735, 'y' => 560]]],
        ];
        return json_encode($json, 320);
    }

    /**
     * 人力资源管理主页
     */
    private function personnelHomePage(): string
    {
        // 搜索文本框
        $searchTxt =
            "<span class=\"search-ico right\" onclick=\"getData()\"></span>"
            . text([
                'name'    => 'dataBoardDate',
                'title'   => "时间段",
                "class"   => "text text-data right contour width200",
                "value"   => date('Y-m') . '-01 ~ ' . date('Y-m-d'),
                'laydate' => ['range' => '~', 'type' => 'date',],
            ]) .
            selectMultiple(["name" => "dataBoardDepartmentId", 'table' => " department", 'class' => " text right contour width200", 'sqlId' => 'id', 'sqlField' => 'name', 'title' => '部门']);

        return <<<EOT
        <div class="home-warp">
            <div class="left-box">
                <div class="quick-entry data-widget">
                    {$this->quickEntry()}
                </div>
                 <div class="data-widget">
                    <p><span class="title-card">数据看板</span>$searchTxt</p>
                    <ul class="revenue-hr" id="hrDataHtml">
                    
                    </ul>
                </div>
                <div class="data-widget left" style="width: 97.4%;">
                    {$this->dataBoardDate(['title' => '入职、离职趋势', 'fun' => 'entryQuitTrend'])}
                </div>
                <div class="half left data-widget">
                    {$this->dataBoardDate(['title' => '入职、离职人员部门分布', 'fun' => 'depDistribute'])}
                </div>
                <div class="half left data-widget">
                    {$this->dataBoardDate(['title' => '离职率趋势', 'fun' => 'turnoverRate'])}
                </div>
            </div>
            <div class="right-box">
                <div class="data-widget">
                    {$this->backlog()}
                </div>
                <div style="overflow: hidden">
                    <div class="data-widget">
                        {$this->message()}
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src='{$this->root}static/javascript/echarts.min.js'></script>
    <script>
        function getData(){
            let date = $('[name="dataBoardDate"]').val(),
                funArray = ['hrData'],
                dataBoardDepartmentId = $('[name="dataBoardDepartmentId"]').val()
            funArray.forEach((fun)=>{
                 $.post(root + 'control/adIndex.html?cla=homepage&fun=' + fun, {date: date,departmentId: dataBoardDepartmentId}, function (res) {
	                 let obj = '#' + fun + 'Html';
	                 $(obj).empty().append(res.html)
                 }, 'json')
            })
        }
        $(function() {
           getData()
        })
    </script>
EOT;
    }

    /**
     * 数据看板
     *
     * @param array $data 格式 [ 'title'=>'标题', 'fun'=>'数据源函数', 'condition'=> '显示查询条件，为空表示显示' ]
     */
    public static function dataBoardDate(array $data): string
    {
        $endDate   = date("Y-m-d");
        $startDate = date("Y-m") . '-01';
        if (isset($data['startDate'])) {
            $startDate = $data['startDate'];
        }
        if (isset($data['endDate'])) {
            $endDate = $data['endDate'];
        }
        $html        = '';
        $isCondition = (!isset($data['condition']) || $data['condition'] !== false);
        if ($isCondition) {
            $dateText = text([
                    "name"    => "date",
                    "title"   => "时间段",
                    "class"   => "text text-data right contour width200",
                    "value"   => $startDate . ' ~ ' . $endDate,
                    'laydate' => ['range' => '~', 'type' => 'date']
                ]) .
                selectMultiple([
                    "name"     => "departmentId",
                    'table'    => " department",
                    'class'    => " text right contour width200",
                    'sqlId'    => 'id',
                    'sqlField' => 'name',
                    'title'    => '部门'
                ]);
            $html     .= <<<EOT
			<form name='{$data['fun']}Form' onsubmit="return searchFormSub('homepage', '{$data['fun']}')">
			    <p>
				<span class="title-card">{$data['title']}</span>
				<span class="search-ico right" onclick="return searchFormSub('homepage', '{$data['fun']}')"></span>
				$dateText
				</p>
			</form>
EOT;
        }
        $isCondition = settype($isCondition, "int");
        $html        .= <<<EOT
<div id='{$data['fun']}Html' class='data-box-show'>数据查询中。。。</div>
EOT;
        if (!in_array($data['title'], ['回款率', '现金占比', '客户来源'])) {
            $html .= <<<eof
            <script>
            $(function(){searchForm('homepage', '{$data['fun']}', 1)})
            </script>
eof;
        }
        //返回
        return $html;
    }

    /**
     * 办公协同主页
     */
    private function administrationHomePage(): string
    {
        return '';
    }

    /**
     * 默认主页
     */
    private function defaultHomePage(): string
    {
        return <<<EOT
        <div class="home-warp">
                <div class="quick-entry data-widget">
                {$this->quickEntry()}
                </div>
                <div class="flex-div">
                     <div class="flex-div-children data-widget h-300 colum-flex">
                        {$this->backlog()}
                    </div>
                    <div class="flex-div-children data-widget h-300 colum-flex">
                       {$this->message()}
                    </div>
                </div>
               
                <div class="flex-div">
                    <div class="flex-div-children data-widget h-300 colum-flex">
                           {$this->myMission()}
                    </div>
                    <div class="flex-div-children data-widget h-300 colum-flex">
                           {$this->notificationMessage('公司通知')}
                    </div>
                   
                </div>
    </div>
    <script src='{$this->root}static/javascript/echarts.min.js'></script>
<style>.home-warp{flex-direction: column}</style>
EOT;
    }

    /**
     * 公司动态和公司通知
     */
    public function notificationMessage($type): string
    {
        $html = '';
        if ($type == '公司动态') {
            $cla = 'news';
        } else {
            $cla = 'notification';
        }
        $num    = 0;
        $result = find(array(
            'table' => 'message',
            'where' => "stid = '{$this->control['stid']}' and type = '$type' and see = '否' order by time asc"
        ));
        foreach ($result['array'] as $array) {
            $num++;
            $html .= "<div class='flex-div msg-item'  onclick=\"window.open('" . root . "control/adIndex.html?cla=$cla&fun=previewPage&source=homepage&id={$array['typeId']}')\"><div class='flex-div-left-message'>{$array['text']}</div><div class='flex-div-right-message'><span class='time'>" . self::formatDate($array['time']) . "</span></div></div>";
        }
        if (empty($html)) {
            $html .= "<div class='flex-div msg-item nodata'>".lang('homePage.nodata')."</div>";
        }
        $companyNoticeText = lang('homePage.companyNotice');
        return <<<eof
<div class="frame-title bottom-line"><span class="title-card">$companyNoticeText($num)</span></div>
<div class="colum-flex-li-1">
    $html
</div>
eof;
    }

    /**
     * 我的任务
     */
    public function myMission(): string
    {
        $html   = '';
        $result = find(array(
            'table' => 'mission',
            'where' => "manager = '{$this->control['stid']}' and workFlow <> '已完成' order by time asc"
        ));
        $num    = 0;
        foreach ($result['array'] as $array) {
            $num++;
            $isOverdue = $array['workFlow'] != '已完成' ? (strtotime($array['endTime']) < time() ? "orange" : '') : (strtotime($array['endTime']) < strtotime($array['completeTime']) ? "orange" : '');
            $html      .= "<div class='flex-div msg-item' onclick=\"newIframe('".lang('homePage.taskDetail')."','" . root . "control/adIndex.html?cla=mission&fun=detail&id={$array['id']}')\"><div class='flex-div-left-message'>{$array['title']}</div><div class='flex-div-right-message'><span class='time $isOverdue'>" . self::formatDate($array['endTime']) . "</span></div></div>";
        }
        if (empty($html)) {
            $html .= "<div class='flex-div msg-item nodata'>".lang('homePage.nodata')."</div>";
        }
        $myTaskText = lang('homePage.myTask');
        return <<<eof
<div class="frame-title bottom-line"><span class="title-card">$myTaskText($num)</span></div>
<div class="colum-flex-li-1">
    $html
</div>
eof;

    }

    /**
     * 学习园地
     */
    public function learningGarden(): string
    {
        $html          = '';
        $idColloection = $this->staffCombination(true);
        $result        = find([
            'table' => 'document',
            'field' => 'id, title,time',
            'where' => " `state` = '已发布' AND ((concat(',',replace(selector,';',','),',') regexp concat(',',replace('{$idColloection}',',',',|,'),','))>0  OR `stid` = '" . self::$stid . "') "
        ]);
        foreach ($result['array'] as $array) {
            $html .= "<li onclick=\"newIframe('文档中心','" . root . "control/adIndex.html?cla=documentCenter&fun=home&id={$array['id']}')\">" . zishu($array['title'], 25) . " <span class='time'>" . self::formatDate($array['time']) . "</span></li>";
        }
        if (empty($html)) {
            $html .= "<li class='flex-div msg-item nodata'>暂无内容</li>";
        }
        return $html;
    }


    /**
     * 获取系统配置下的所有三级菜单
     */
    public function getThreeAll(): array
    {
        $array = [];
        foreach ((array)$this->powerAllLang as $oneKey => $twoArray) {
            foreach ((array)$twoArray as $twoKey => $threeArray) {
                foreach ((array)$threeArray as $threeKey => $fourArray) {
                    foreach ((array)$fourArray as $key => $value) {
                        if(!isset($value['name'])){
                            var_dump($value);
                        }
                        $array[$key] = [
                            'name'      => $value['name'],
                            'cla'      => $value['cla'] ?? '',
                            'fun'      => $value['fun'] ?? '',
                            'menuOne'   => $oneKey,
                            'menuTwo'   => $twoKey,
                            'menuThree' => $threeKey,
                        ];
                    }

                }
            }
        }
        return $array;
    }

    /**
     * 获取当前用户权限的所有三级菜单key
     *
     * @return array
     */
    public function getUserThreeAll(): array
    {
        return array_keys($this->controlPower);
    }

    /**
     * 获取用户配置的快捷入口key
     *
     * @return array
     */
    public static function getUserQuick(): array
    {
        return (array)json_decode(self::$user['quick'], 320);
    }

    public function quickEntry(): string
    {
        $setIco = $this->root . 'img/control/setting.svg';
        // 获取该用户当前权限
        $userPower = $this->getUserThreeAll();
        // 用户快捷入口
        $quick = self::getUserQuick();
        // 权限与实际key交集
        $array = array_intersect($userPower, $quick);
        // 所有三级菜单
        $threeAll = $this->getThreeAll();
        // 构造链接
        $html = '';
        $num  = 0;
        foreach ($array as $key) {
            if(!isset($threeAll[$key])){
                continue;
            }
            $title = $threeAll[$key]['name'];
            if ($title) {
                $num++;
                $root = $threeAll[$key]['cla'] ?
                    $this->root . 'control/adIndex.html?cla=' . $threeAll[$key]['cla'] . '&fun='.$threeAll[$key]['fun'] :
                    $this->root . 'control/adIndex.html?cla=' . $key . '&fun=home';
                $path = implode(' > ',[$threeAll[$key]['menuOne'],$threeAll[$key]['menuTwo'],$threeAll[$key]['menuThree'],$threeAll[$key]['name']]);
                $html .= "<li title='{$path}' onclick=\"newIframe('$title', '$root','{$threeAll[$key]['menuOne']}','{$threeAll[$key]['menuTwo']}', true)\">$title</li>\n";
            }
        }
        $title = lang('homePage.title');
        $setTitle = lang('homePage.setTitle');
        return <<<EOT
        <p><span class="title-card">$title($num)</span> <span class="setting-ico">
        <img src="$setIco" title="$setTitle" onclick="newIframe('$setTitle','{$this->root}control/adIndex.html?cla=homepage&fun=setQuickEntry')" alt=""></span></p>
        <ul>
            $html
        </ul>
EOT;
    }


    /**
     * 快捷入口
     */
    public function setQuickEntry(): string
    {
        //定义参数
        $data = [
            'power' => false,
            'onion' => [
                '主页', '设置快捷入口',
            ],
        ];
        //权限
        $quickEntryHtml = "";
        $line           = '';
        foreach ($this->powerAllLang as $oneKey => $twoArray) {
            $secondary = '';
            $oneBox    = '';
            // 过滤未配置的一级菜单
            if ($twoArray) {
                foreach ($twoArray as $twoKey => $threeArray) {
                    $twoBox = '';
                    // $checkAll = "checked";
                    // 过滤空二级菜单
                    if ($threeArray) {
                        // 获取该用户当前权限
                        $userPower = $this->getUserThreeAll();
                        // 用户配置的快捷入口
                        $quick = self::getUserQuick();
                        foreach ($threeArray as $threeKey => $fourArray) {
                            $box      = '';
                            $fourFlag = false;
                            $valArray = $checked = [];
                            foreach ($fourArray as $menuFourKey => $menuFour) {
                                if (!$menuFour['name'] || !$menuFour) {
                                    continue;
                                }
                                // 没有权限跳过
                                if (!in_array($menuFourKey, $userPower)) {
                                    continue;
                                }
                                $valArray[$menuFourKey] = $menuFour['name'];
                                // 选中
                                if (in_array($menuFourKey, $quick)) {
                                    $checked[] = $menuFourKey;
                                }
                                $fourFlag = true;
                            }
                            $box .= checkbox(["name" => "quick[" . $threeKey . "]", "value" => $valArray, "checked" => $checked]);
                            // 是否全部选中
                            $checkAll = (count($valArray) == count($checked)) ? 'checked' : '';
                            // 标题
                            $title  = ($threeKey != $secondary) ? '<label class="checkbox"><input value="quick[' . $threeKey . ']" type="checkbox" onchange="checkboxAll(this)"' . $checkAll . '><span></span>' . "\n$threeKey" . '：</label>' : '';
                            $twoBox .= ($fourFlag === true) ? ('<div class="secondary-box">' . $title . $box . '</div>') : '';
                        }
                        $oneBox .= '<div class="box ' . $line . '"><h4 class="one-title">' . $oneKey . '->' . $twoKey . '</h4>' . $twoBox . "</div>";
                        $line   = "line";//分隔线
                    }
                }
                $quickEntryHtml .= $oneBox;

            }
        }
        $button[]       = [
            "name"  => '保存',
            "type"  => "点击事件",
            "cla"   => $this->get('cla'),
            "fun"   => "subForm('setQuickEntryForm', root+'control/adIndex.html?cla=" . $this->get('cla') . "&fun=setQuickEntryEdit')",
            "post"  => ["id" => $this->get('id')],
            'style' => 'li-btn-blue-bg',
        ];
        $data['button'] = $this->tableShowButton($button);
        //编辑页表单数组
        $data['html'] = "<form name='setQuickEntryForm'>" . $quickEntryHtml . "</form>";
        return $this->tab($data);
    }

    /**
     * 保存设置
     */
    public function setQuickEntryEdit(): string
    {
        $quick = $this->post('quick') ?: [];
        $type  = $this->post('type');
        $power = [];
        foreach ($quick as $val) {
            $power = array_merge($power, $val);
        }
        if ($type === 'add') {
            $userQuick = self::getUserQuick();
            if (count(array_diff($power, $userQuick)) > 0) {
                $power = array_merge($userQuick, $power);
                $msg   = '快捷入口设置成功';
            } else {
                $power = array_diff($userQuick, $power);
                $msg   = '快捷入口取消成功';
            }
        }
        $json['warn'] = update([
            "table" => "user",
            "field" => [
                'quick' => json_encode($power, 320),
            ],
            "where" => " uid = '" . self::$user['uid'] . "' ",
        ]);
        if (in_array($json['warn'], ["新增成功", "更新成功"])) {
            //提示
            if (empty($type)) {
                $_SESSION['warn'] = "快捷入口设置成功";
                //返回
//                    $json['href'] = root . "control/adIndex.html?cla=homepage&fun=home";
            } else {
                $json['msg'] = $msg ?? '';
            }
            $json['warn'] = 2;
        }
        return json_encode($json, 320);
    }

    /**
     * 待办事项
     */
    public function backlog(): string
    {
        //赋值
        //数据查询
        $result = find(array(
            "table" => "backlog",
            "where" => " stid = '" . $this->control['stid'] . "' and workFlow = '待处理' order by FIELD(urging,'是','否'),time asc"
        ));
        $ul     = '<div class="colum-flex-li-1">';
        $num    = 0;
        if (!$result['array']) {
            $ul .= '<li class="flex-div msg-item nodata">'.lang('homePage.nodata').'</li>';
        } else {
            foreach ($result['array'] as $array) {
                if ($array['startDay'] <= date("Y-m-d")) {
                    $info = query('audit', " id ='$array[typeId]'");
                    $urge = ($array['urging'] == '是') ? ("<span style='color: #ff0000'>[" .lang('homePage.urge')."]</span>") : '';
                    if (!empty($array['targetCla']) && !empty($array['targetFun']) && empty($info['id'])) {
                        $ul .= "<div onclick=\"preValidationCoid(this,'{$array['coid']}')\" data-fun=\"newIframe('{$array['type']}详情','" . root . "control/adIndex.html?cla={$array['targetCla']}&fun={$array['targetFun']}&id={$array['typeId']}')\" class='flex-div msg-item'><div class='flex-div-left-message'>" . $urge . $array['text'] . "</div><div class='flex-div-right-message'><span class='time'>" . self::formatDate($array['time']) . "</span></div></div>";
                    } elseif ($info['id']) {
                        $ul .= "<div onclick=\"preValidationCoid(this,'{$array['coid']}')\" data-fun=\"newIframe('{$array['type']}详情','" . root . "control/adIndex.html?cla={$info['targetCla']}&fun={$info['targetFun']}&id={$info['targetId']}')\" class='flex-div msg-item'><div class='flex-div-left-message'>" . $urge . $array['text'] . "</div><div class='flex-div-right-message'><span class='time'>" . self::formatDate($array['time']) . "</span></div></div>";
                    }
                    $num++;
                }
            }
        }
        $ul .= '</div>';
        $backlogText = lang('homePage.backlog');
        $moreText = lang('homePage.more');
        $myBacklogText = lang('homePage.myBacklog');
        // 拼接字符串
        return <<<EOT
        <div class="frame-title bottom-line"><span class="title-card">$backlogText($num)</span><span class="more-ico"><img title="$moreText" src="{$this->root}img/control/more.svg" onclick="newIframe('$myBacklogText','{$this->root}control/adIndex.html?cla=backlog&fun=home')" alt=""></span></div>
        $ul
EOT;
    }

    /**
     * 菜单搜索
     *
     * @return false|string
     */
    public function menuSearch(): bool|string
    {
        $key          = $this->post('keyword');//关键词
        $result       = $this->getUserMenu($key);
        $json['warn'] = 2;
        $json['data'] = [];
        foreach ($result as $val) {
            $json['data'][] = array(
                'title'         => $val['name'],
                'menuOneName'   => $val['menuOneName'],
                'menuTwoName'   => $val['menuTwoName'],
                'menuThreeName' => $val['menuThreeName'],
                'id'            => $val['power'],
                'url'           => $val['url']
            );
        }
        return json_encode($json, 320);
    }

    /**
     * 获取用户菜单
     *
     * @param $key
     * @return array
     */
    public function getUserMenu($key): array
    {
        $menu = [];
        if (is_array($this->powerAllLang)) {
            $userPower = $this->getUserThreeAll();
            foreach ($this->powerAllLang as $menuOneName => $menuOne) {
                foreach ($menuOne as $menuTwoName => $menuTwo) {
                    foreach ($menuTwo as $menuThreeName => $menuThree) {
                        foreach ($menuThree as $menuFourName => $value) {
                            if (in_array($menuFourName, $userPower) && str_contains($value['name'], $key)) {
                                if (empty($value['cla']) or empty($value['fun'])) {
                                    //如果没有定义类或函数名称，则使用模块名称作为类名称
                                    $iframeHref = "control/adIndex.html?cla=" . $menuFourName . "&fun=home";
                                } else {
                                    $iframeHref = "control/adIndex.html?cla=" . $value['cla'] . "&fun=" . $value['fun'];
                                }
                                $menu[] = [
                                    'power'         => $menuFourName,
                                    'name'          => $value['name'],
                                    'menuOneName'   => $menuOneName,
                                    'menuTwoName'   => $menuTwoName,
                                    'menuThreeName' => $menuThreeName,
                                    'url'           => $iframeHref,
                                ];
                            }
                        }

                    }
                }
            }
        }
        return $menu;
    }

    /**
     * 消息中心
     */
    public function message(): string
    {
        //数据查询
        $message = find(array(
            "table" => "message",
            "where" => " stid = '" . $this->control['stid'] . "' and type not in ('公司通知') and see = '否' order by time desc"
        ));
        $ul      = '<div class="colum-flex-li-1">';
        $i       = 0;
        if ($message['array']) {
            foreach ($message['array'] as $array) {
                $info = query('audit', " id ='$array[typeId]'");
                if (!empty($array['targetCla']) && !empty($array['targetFun']) && empty($info['id'])) {
                    $ul .= "<div class='flex-div msg-item' onclick=\"see('{$array['type']}','{$array['targetCla']}','{$array['targetFun']}','{$array['typeId']}','{$array['id']}')\"><div class='flex-div-left-message'>{$array['text']}</div><div class='flex-div-right-message'><span class='time'>" . self::formatDate($array['time']) . "</span></div></div>";
                } else {
                    $ul .= "<div class='flex-div msg-item' onclick=\"see('{$array['type']}','{$info['targetCla']}','{$info['targetFun']}','{$info['targetId']}','{$array['id']}')\"><div class='flex-div-left-message'>{$array['text']}</div><div class='flex-div-right-message'><span class='time'>" . self::formatDate($array['time']) . "</span></div></div>";
                }
                $i++;
            }
        }
        if ($i == 0 || !$message['array']) {
            $ul .= '<div class="flex-div msg-item nodata">'.lang('homePage.nodata').'</div>';
        }
        $ul .= '</div>';
        $moreText = lang('homePage.more');
        $messageText = lang('homePage.message');
        $setReadText = lang('homePage.setRead');
        $myMessageText = lang('homePage.myMessage');
        // 拼接字符串
        return <<<EOT
        <div class="frame-title bottom-line "><span class="title-card">$messageText($i)</span>&nbsp;|&nbsp;<span onclick="href('control/adIndex.php?cla=message&fun=read')">$setReadText</span><span class="more-ico"><img title="$moreText" src="{$this->root}img/control/more.svg" onclick="newIframe('$myMessageText','{$this->root}control/adIndex.html?cla=message&fun=home')" alt=""></span></div>
        $ul
        <script>
        function see(type,targetCla,targetFun,targetId,messageId){
            $.post(root+'control/adIndex.html?cla=homepage&fun=see',{messageId:messageId},function(res) {
               if (res.warn ===2){
                    newIframe(type+'详情',root+'control/adIndex.html?cla='+targetCla+'&fun='+targetFun+'&id='+targetId)
               }else{
                   warn(res.warn);
               }
            },'json')
        }
</script>
EOT;
    }

    /**
     * 预警消息
     */
    public function alertMessage(): string
    {
        //数据查询
        $message = find(array(
            "table" => "message",
            "where" => " stid = '" . $this->control['stid'] . "' and type = '预警消息' and see = '否' order by time desc "
        ));
        $ul      = '<ul class="right-box-ul">';
        $i       = 0;
        if ($message['array']) {
            foreach ($message['array'] as $array) {
                $info = query('audit', " id ='$array[typeId]'");
                if (!empty($array['targetCla']) && !empty($array['targetFun']) && empty($info['id'])) {
                    $ul .= "<li onclick=\"see('{$array['type']}','{$array['targetCla']}','{$array['targetFun']}','{$array['typeId']}','{$array['id']}')\">" . zishu($array['text'], 18) . " <span class='time'>" . self::formatDate($array['time']) . "</span></li>";
                } else {
                    $ul .= "<li onclick=\"see('{$array['type']}','{$info['targetCla']}','{$info['targetFun']}','{$info['targetId']}','{$array['id']}')\">" . zishu($array['text'], 18) . " <span class='time'>" . self::formatDate($array['time']) . "</span></li>";
                }
                $i++;
            }
        }
        if ($i == 0 || !$message['array']) {
            $ul .= '<li class="flex-div msg-item nodata">暂无内容</li>';
        }
        $ul .= '</ul>';
        // 拼接字符串
        return <<<EOT
        <p><span class="title-card">预警消息</span></p>
        $ul
        <script>
        function see(type,targetCla,targetFun,targetId,messageId){
            $.post(root+'control/adIndex.html?cla=homepage&fun=see',{messageId:messageId},function(res) {
               if (res.warn ===2){
                    newIframe(type+'详情',root+'control/adIndex.html?cla='+targetCla+'&fun='+targetFun+'&id='+targetId)
               }else{
                   warn(res.warn);
               }
            },'json')
        }
</script>
EOT;
    }


    /**
     * 更新消息状态
     *
     * @return string
     */
    public function see(): string
    {
        $id   = $this->post('messageId');
        $warn = update(array(
            'table' => 'message',
            'field' => ['see' => '是', 'seeTime' => $this->time],
            'where' => " id = $id"
        ));
        if ($warn == '更新成功') {
            $json['warn'] = 2;
        } else {
            $json['warn'] = '查看失败';
        }
        return json_encode($json, 320);
    }

    /**
     * 数据看板
     *
     * @param array $data 格式 [ 'title'=>'标题', 'fun'=>'数据源函数', 'condition'=> '显示查询条件，为空表示显示' , 'query_item'=> '自定义查询条件' ]
     */
    public static function dataBoard(array $data): string
    {
        $endMoon   = date("Y-m");
        $startMoon = date("Y-m", strtotime('-1 month'));
        if (isset($data['startDate'])) {
            $startMoon = $data['startDate'];
        }
        if (isset($data['endDate'])) {
            $endMoon = $data['endDate'];
        }
        $html        = '';
        $isCondition = (!isset($data['condition']) || $data['condition'] !== false);
        if ($isCondition) {
            if (!isset($data['query_item'])) {
                $dateText = text([
                    "name"    => "months",
                    "title"   => "时间段",
                    "class"   => "text text-data right contour width200",
                    "value"   => $startMoon . ' ~ ' . $endMoon,
                    'laydate' => ['range' => '~', 'type' => 'month']
                ]);
            } elseif ($data['query_item'] == 'client') {
                $dateText = text([
                        'name'    => 'months',
                        'title'   => "时间段",
                        "class"   => "text text-data right contour width200",
                        "value"   => date('Y-m', strtotime('-11 month')) . ' ~ ' . date('Y-m'),
                        'laydate' => ['range' => '~', 'type' => 'month',],
                    ]) .
                    selectMultiple([
                        "name"     => "staffId",
                        'table'    => " staff",
                        'class'    => " text right contour width200",
                        'sqlId'    => 'stid',
                        'sqlField' => 'name',
                        'where'    => " state <> '离职' ",
                        'title'    => '员工'
                    ]);
            }
            $html .= <<<EOT
			<form name='{$data['fun']}Form' onsubmit="return searchFormSub('homepage', '{$data['fun']}')">
			    <p>
				<span class="title-card">{$data['title']}</span>
				<span class="search-ico right" onclick="return searchFormSub('homepage', '{$data['fun']}')"></span>
				$dateText
				</p>
			</form>
EOT;
        }
        $isCondition = settype($isCondition, "int");
        $html        .= <<<EOT
<div id='{$data['fun']}Html' class='data-box-show'>数据查询中。。。</div>
EOT;
        if (!in_array($data['title'], ['回款率', '现金占比', '客户来源'])) {
            $html .= <<<eof
            <script>
            $(function(){searchForm('homepage', '{$data['fun']}', 1)})
            </script>
eof;
        }
        //返回
        return $html;
    }

    /**
     * 离职趋势 数据
     *
     * @return string
     */
    public function turnoverRate(): string
    {
        $date         = $this->post('date');
        $departmentId = $this->post('departmentId');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m') . '-01';
            $timeArr[1] = $this->date;
        }
        $dateArr = self::getDatesBetweenTwoDays($timeArr[0], $timeArr[1]);
        $res     = [];
        $and     = '';
        $and2    = '';
        if ($departmentId) {
            $departments = self::getDepartmentSub(["where" => " pid = '$departmentId' "]);
            $departments = array_merge([$departmentId], explode(',', trim($departments)));
            $and         .= "  and jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ";
            $and2        .= "  and st.jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ";
        }
        foreach ($dateArr as $date) {
            $quitNum      = find([
                'table'  => "staff_quit_record",
                'field'  => "IFNULL(count(id),0) as num",
                'single' => " state = '已通过' and confirmDate = '$date' " . $and,
            ])['num'] ?? 0;
            $entryNum     = find([
                'table'  => "staff_entry_record",
                'field'  => "IFNULL(count(id),0) as num",
                'single' => " state = '已通过' and entryDate = '$date' " . $and,
            ])['num'] ?? 0;
            $onJobNum     = find([
                'table'  => "staff as st left join staff_entry_record as ent on st.talentId = ent.talentId",
                'field'  => "IFNULL(count(st.stid),0) as num",
                'single' => " 1=1  and (
            (date_format(ent.entryDate, '%Y-%m-%d') < '" . $date . "' and (date_format(st.quitDay, '%Y-%m-%d') >= '" . $date . "' or st.quitDay is null)) or (ent.talentId is null and (st.quitDay is null or date_format(st.quitDay, '%Y-%m-%d') >= '" . $date . "'))
            ) " . $and2,
            ])['num'] ?? 0;
            $onJobTotal   = $entryNum + $onJobNum;
            $turnoverRate = $onJobTotal == 0 ? 0 : round($quitNum / $onJobTotal * 100, 2);
            $res[]        = [
                'date'         => $date,
                'turnoverRate' => $turnoverRate,
            ];
        }
        $data         = [
            "name"   => array_column($res, 'date'),
            "series" => [
                [
                    'name' => '离职率',
                    'data' => array_column($res, 'turnoverRate'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data);
        return json_encode($json, 320);
    }


    /**
     * @param array $data
     * @return string
     */
    public static function getDepartmentSub($data = [])
    {
        // 条件
        $data['where'] = $data['where'] ?? "pid='0'";
        // 结果
        $result = find(['table' => 'department', 'where' => $data['where'] . " order by list asc"]);
        $temp   = "";
        if ($result['array']) {
            foreach ($result['array'] as $value) {
                // 判断下级是否存在
                $data['where'] = " pid='{$value['id']}' ";
                $has           = query('department', $data['where']);
                if ($has['id']) {
                    $temp .= $value['id'] . ",";
                    $temp .= self::getDepartmentSub($data);
                } else {
                    $temp .= $value['id'] . ",";
                }
            }
        }
        return $temp;
    }

    /**
     * 入职、离职人员部门分布 - 返回数据
     */
    public function depDistribute(): bool|string
    {
        $date = $this->post('date');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m') . '-01';
            $timeArr[1] = $this->date;
        }
        $department = $this->post('departmentId');
        if (empty($department)) {
            $arr = find([
                'table' => "department",
                'field' => "id,name",
                'where' => " pid = '0' ",
            ]);
        } else {
            $arr = find([
                'table' => "department",
                'field' => "id,name",
                'where' => " pid = '$department' ",
            ]);
            if (static::isNull($arr['array'])) {
                $query          = query("department", " id = '$department' ", 'id,name');
                $arr['array'][] = $query;
            }
        }
        $res = [];
        foreach ((array)$arr['array'] as $array) {
            $departments = self::getDepartmentSub(["where" => " pid = '$array[id]' "]);
            $departments = array_merge([$array['id']], explode(',', trim($departments)));
            $res[]       = [
                'department' => $array['name'],
                'entryNum'   => find([
                        'table'  => "staff_entry_record",
                        'field'  => "IFNULL(count(id),0) as num",
                        'single' => " state = '已通过' and entryDate between '$timeArr[0]' and '$timeArr[1]' and jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ",
                    ])['num'] ?? 0,
                'quitNum'    => find([
                        'table'  => "staff_quit_record",
                        'field'  => "IFNULL(count(id),0) as num",
                        'single' => " state = '已通过' and confirmDate between '$timeArr[0]' and '$timeArr[1]' and jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ",
                    ])['num'] ?? 0,
            ];
        }
        $data         = [
            "name"   => array_column($res, 'department'),
            "series" => [
                [
                    'name' => '入职',
                    'data' => array_column($res, 'entryNum'),
                ],
                [
                    'name' => '离职',
                    'data' => array_column($res, 'quitNum'),
                ],
            ],
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }

    /**
     * 入职、离职趋势 数据
     *
     * @return string
     */
    public function entryQuitTrend(): string
    {
        $date         = $this->post('date');
        $departmentId = $this->post('departmentId');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m') . '-01';
            $timeArr[1] = $this->date;
        }
        $dateArr = self::getDatesBetweenTwoDays($timeArr[0], $timeArr[1]);
        $res     = [];
        $and     = '';
        if ($departmentId) {
            $departments = self::getDepartmentSub(["where" => " pid = '$departmentId' "]);
            $departments = array_merge([$departmentId], explode(',', trim($departments)));
            $and         .= "  and jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ";
        }
        foreach ($dateArr as $date) {
            $res[] = [
                'date'     => $date,
                'entryNum' => find([
                        'table'  => "staff_entry_record",
                        'field'  => "IFNULL(count(id),0) as num",
                        'single' => " state = '已通过' and entryDate = '$date' " . $and,
                    ])['num'] ?? 0,
                'quitNum'  => find([
                        'table'  => "staff_quit_record",
                        'field'  => "IFNULL(count(id),0) as num",
                        'single' => " state = '已通过' and confirmDate = '$date' " . $and,
                    ])['num'] ?? 0,
            ];
        }

        $data         = [
            "name"   => array_column($res, 'date'),
            "series" => [
                [
                    'name' => '入职',
                    'data' => array_column($res, 'entryNum'),
                ],
                [
                    'name' => '离职',
                    'data' => array_column($res, 'quitNum'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data, 'area');
        return json_encode($json, 320);
    }

    /**
     * 获取两个时间之间的日期
     *
     * @param $startDate
     * @param $endDate
     * @return array
     */
    public static function getDatesBetweenTwoDays($startDate, $endDate)

    {
        $dates = [];
        if (strtotime($startDate) > strtotime($endDate)) {
            $temp      = $startDate;
            $startDate = $endDate;
            $endDate   = $temp;
        }

        if ($startDate == $endDate) {
            // 开始日期与结束日期是同一天时
            array_push($dates, $startDate);
            return $dates;
        } else {
            array_push($dates, $startDate);
            $currentDate = $startDate;
            do {
                $nextDate = date('Y-m-d', strtotime($currentDate . ' +1 days'));
                array_push($dates, $nextDate);
                $currentDate = $nextDate;
            } while ($endDate != $currentDate);
            return $dates;
        }
    }

    /**
     * 总营收
     *
     * @return string
     */
    public function hrData(): string
    {
        //总营收 = 销售收入
        $date         = $this->post('date') ?: date('Y-m') . '-01 ~ ' . date('Y-m-d');
        $departmentId = $this->post('departmentId');
        $and          = "";
        $entryAnd     = "";
        $quitAnd      = "";
        if ($date) {
            $entryAnd .= $this->timeComparison($date, 'date', 'entryDate');
            $quitAnd  .= $this->timeComparison($date, 'date', 'quitDate');
        }
        if ($departmentId) {
            $departments = self::getDepartmentSub(["where" => " pid = '$departmentId' "]);
            $departments = array_merge([$departmentId], explode(',', trim($departments)));
            $entryAnd    .= "  and jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ";
            $quitAnd     .= "  and jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ";
            $and         .= "  and st.jobId in (select id from job where departmentId in ('" . implode("','", $departments) . "')) ";
        }
        $entryNum = find([
            'table'  => "staff_entry_record",
            'field'  => "IFNULL(count(id),0) as num",
            'single' => " state = '已通过' " . $entryAnd,
        ])['num'] ?? 0;
        $quitNum  = find([
            'table'  => "staff_quit_record",
            'field'  => "IFNULL(count(id),0) as num",
            'single' => " state = '已通过' " . $quitAnd,
        ])['num'] ?? 0;
        $data     = explode('~', $date);
        if (is_array($data)) {
            $startStamp = strtotime(trim($data[0]));
            $endStamp   = strtotime(trim(end($data)));
            //查询条件说明，期初在职人数，1、入职时间小于筛选时间段的开始时间，并且离职时间大于等于筛选时间段的开始或者未离职，2、没有入职记录，并且未离职或离职时间大于等于筛选时间段的开始
            $and .= " and (
            (date_format(ent.entryDate, '%Y-%m-%d') < '" . date('Y-m-d', $startStamp) . "' and (date_format(st.quitDay, '%Y-%m-%d') >= '" . date('Y-m-d', $startStamp) . "' or st.quitDay is null)) or (ent.talentId is null and (st.quitDay is null or date_format(st.quitDay, '%Y-%m-%d') >= '" . date('Y-m-d', $startStamp) . "'))
            ) ";
        }
        $onJobNum     = find([
            'table'  => "staff as st left join staff_entry_record as ent on st.talentId = ent.talentId",
            'field'  => "IFNULL(count(st.stid),0) as num",
            'single' => " 1=1 " . $and,
        ])['num'] ?? 0;
        $inJobNum     = $onJobNum + $entryNum;
        $turnoverRate = $inJobNum == 0 ? 0 : round($quitNum / $inJobNum * 100, 2);
        $json['html'] = <<<EOT
        <li class="vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">入职人数</p>
                <p class="hr-p f-30">$entryNum</p>
            </div>
        </li>
        <li class="vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">离职人数</p>
                <p class="hr-p f-30">$quitNum</p>
            </div>
        </li>
        <li class="vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">在职人数</p>
                <p class="hr-p f-30">$onJobNum</p>
            </div>
        </li>
        <li class="vertical-line-hr">
            <div class="hr-div">
                <p class="hr-p gray f-14">离职率</p>
                <p class="hr-p f-30">$turnoverRate%</p>
            </div>
        </li>
EOT;
        return json_encode($json, 320);
    }

    /**
     * 销售成本
     */
    public static function costOfSales($num): float
    {
        $totalMoney = find([
            'table'  => "machining_in_order as a join machining_in_order_detail as b on a.id = b.orderId",
            'field'  => "(b.fee+b.energyFee+((select ifnull(sum(num),0) from inventory_detail where sourceId = b.id)*b.price)) as money",
            'single' => " a.state = '已确认' ",
        ])['money'] ?? 0;
        $totalNum   = find([
            'table'  => "machining_in_order as a join machining_in_order_detail as b on a.id = b.orderId",
            'field'  => "(select ifnull(sum(num),0) from inventory_detail where sourceId = b.id) as num",
            'single' => " a.state = '已确认' ",
        ])['num'] ?? 0;
        return $totalNum > 0 ? ($totalMoney / $totalNum * $num) : 0;
    }

    /**
     * 总营收
     *
     * @return string
     */
    public function totalRevenue(): string
    {
        //总营收 = 销售收入
        $month     = $this->post('months');
        $whereSale = $whereInventory = $whereFreight = "";
        if ($month) {
            $whereSale      .= $this->timeComparison($month, 'month', 'main.recordDate');
            $whereInventory .= $this->timeComparison($month, 'month', 'main.sourceDate');
            $whereFreight   .= $this->timeComparison($month, 'month', 'ord.recordDate');
        }
        //发货出库金额
        $out_cost_money = find(array(
            "table"  => " inventory_changes_detail as detail join inventory_changes as main on detail.orderId = main.id join inventory_detail as mx on mx.id = detail.sourceId ",
            "field"  => " ifnull(sum(detail.money),0) as money ",
            "single" => " main.state in ('已出库','已复核') and main.coid = '" . self::$coid . "' and mx.sourceTable = 'sale_send_order_detail' {$whereSale} "
        ))['money'];
        //退货入库金额
        $in_cost_money = find(array(
            "table"  => " inventory_changes_detail as detail join inventory_changes as main on detail.orderId = main.id join inventory_detail as mx on mx.id = detail.sourceId ",
            "field"  => " ifnull(sum(detail.money),0) as money ",
            "single" => " main.state in ('已入库','已复核') and main.coid = '" . self::$coid . "' and mx.sourceTable = 'sale_refund_order_detail' {$whereSale} "
        ))['money'];
        $cost          = self::formattingFigure($out_cost_money - $in_cost_money);
        //销售发货金额
        $out_Money = find(array(
            "table"  => " inventory_detail as detail join inventory as main on detail.orderId = main.id ",
            "field"  => " ifnull(sum(detail.money),0) as money ",
            "single" => " detail.coid = '" . self::$coid . "' and detail.sourceTable = 'sale_send_order_detail' {$whereInventory} "
        ))['money'];
        //退货金额
        $refund_Money = find(array(
            "table"  => " inventory_detail as detail join inventory as main on detail.orderId = main.id ",
            "field"  => " ifnull(sum(detail.money),0) as money ",
            "single" => " detail.coid = '" . self::$coid . "' and detail.sourceTable = 'sale_refund_order_detail' {$whereInventory} "
        ))['money'];
        $income       = round($out_Money - $refund_Money, 2);  //收入
        //分摊运费
        $freightMoney = find(array(
            "table"  => " sale_send_order_loading as loading join sale_send_order as ord on loading.orderId = ord.id ",
            "field"  => " ifnull(sum(loading.freight),0) as freight ",
            "single" => " ord.coid = '" . self::$coid . "' and ord.state = '已确认' {$whereFreight} "
        ))['freight'];

        $grossProfit = round($income - $cost - $freightMoney, 2);

        $result = [
            'income' => $income,
            'cost'   => $cost,
            'margin' => $grossProfit,
        ];
        return <<<EOT
        <p>总营收</p>
        <hr class="pad10 mag10">
        <hr class="pad10 mag10">
        <h3 id="totalRevenue"><b>￥{$this->formateNumber($result['income'], "万")}</b></h3>
        <hr class="pad10 mag10">
        <p class="gray" id="cost-profit">成本 {$this->formateNumber($result['cost'], "万")}，毛利{$this->formateNumber($result['margin'], "万")}</p>
EOT;
    }

    /**
     * 回款率 - 返回数据
     *
     * @return string
     */
    public function receivableData(): string
    {
        $where = " a.type = '客户' ";
        $month = $this->post('months');
        if (!static::isNull($month)) {
            $where .= self::timeComparison($month, 'month', 'targetDate');
        }
        //销售金额
        $saleMoney = find([
            "table" => "record as a join kehu as b on a.typeId = b.khid",
            'sum'   => "money",
            "where" => $where . " AND a.classify not in  ('收款单核销', '核销') ",
        ]);
        //实际收款金额
        $recMoney = find([
            "table" => "record as a join kehu as b on a.typeId = b.khid",
            'sum'   => "money",
            "where" => $where . " AND a.classify in  ('收款单核销', '核销') ",
        ]);
        // 回款率=已回款/应回款
        $ratio        = $saleMoney > 0 ? round(($recMoney / $saleMoney) * 100, 2) : 0;
        $unit         = static::$unit;
        $html         = <<<EOT
        <div class="right receivableData gray">
            <p>应回款 $unit {$this->formateNumber($saleMoney, "万")}</p>
            <p>已回款 $unit {$this->formateNumber($recMoney != 0 ? (-1 * $recMoney) : 0, "万")} </p>
            <p>回款率 $ratio %</p>
        </div>
EOT;
        $data         = [
            "series" => [
                [
                    'name' => '回款率',
                    'data' => $ratio / 100, //不能大于1
                ],
            ],
        ];
        $json['html'] = $this->liquidfill($data) . $html;
        return json_encode($json, 320);
    }

    /**
     * 现金占比 - 返回数据
     *
     * @return string
     */
    public function cashRatioData(): string
    {
        function calc($obj, $type, $month = null)
        {
            $where = " r.state = '已确认' ";
            if (!$obj::isNull($month)) {
                $where .= $obj->timeComparison($month, 'month', 'recordDate');
            }
            return find([
                "table" => "receipt_detail as d join receipt as r on d.orderId = r.id",
                'sum'   => "money",
                "where" => $where . " AND d.settleType = '$type' and r.classify=1",
            ]);
        }

        // 日期条件
        $month        = $this->post('months');
        $cash         = calc($this, '现金', $month);
        $bill         = calc($this, '票据', $month);
        $sum          = $cash + $bill;
        $cashRate     = ($sum > 0) ? $cash / $sum : 0;
        $billRate     = ($sum > 0) ? $bill / $sum : 0;
        $html         = '
        <div class="gray cash-ratio-span">现金 ' . $this->formateNumber($cash, '万') . '，票据 ' . $this->formateNumber($bill, '万') . '</div>';
        $data         = [
            "series" => [
                [
                    'name' => '现金',
                    'data' => $cashRate, //不能大于1
                ],
                [
                    'name' => '票据',
                    'data' => $billRate,
                ],
            ],
        ];
        $json['html'] = $this->contrast($data) . $html;
        return json_encode($json, 320);
    }

    /**
     * 客户来源 - 返回数据
     *
     * @return string
     */
    public function clientSourceData(): string
    {
        return (new customerAnalysisClass())->clientSourceData($this->post('months'));
    }

    /**
     * 销售漏斗 - 返回数据
     *
     * @return string
     */
    public function cluesData(): string
    {
        $where = '';
        $month = $this->post('months');
        if (!static::isNull($month)) {
            $where .= self::timeComparison($month, 'month');
        }
        $tableArray = ['线索', '潜在客户', '目标客户', '商机', '成交'];
        $result     = [];
        foreach ($tableArray as $type) {
            $total    = match ($type) {
                '线索' => static::total([
                    'table' => 'clue',
                    'where' => $where,
                ]),
                '潜在客户' => static::total([
                    'table' => 'kehu',
                    'where' => " `workFlow` in ('初次联系', '跟进客户')" . $where,
                ]),
                '目标客户' => static::total([
                    'table' => 'kehu',
                    'where' => " `workFlow` ='意向客户' " . $where,
                ]),
                '商机' => static::total([
                    'table' => 'opportunity',
                    'where' => " `stage` = '已签单' " . $where,
                ]),
                '成交' => static::total([
                    'table' => 'sales_contract',
                    'where' => " `state` ='已通过' " . $where,
                ]),
            };
            $result[] = [
                'name' => $type,
                'data' => $total,
            ];
        }
        $data['series'] = $result;
        $json['html']   = $this->funnel($data);
        return json_encode($json, 320);
    }

    /**
     * 行业与规模客户数 - 返回数据
     *
     * @return string
     */
    public function industryScale(): string
    {
        return (new customerAnalysisClass())->industryScale($this->post('months'));
    }

    /**
     * 项目进度 - 返回数据
     *
     * @return string
     */
    public function progressData(): string
    {
        $data         = [
            "series" => [
                [
                    'name' => '调研需求',
                    'data' => ['2021-04-18', '2021-04-19'],
                ],
                [
                    'name' => '制定方案',
                    'data' => ['2021-04-19', '2021-04-22'],
                ],
                [
                    'name' => '设计原型',
                    'data' => ['2021-04-22', '2021-04-25'],
                ],
                [
                    'name' => '代码编写',
                    'data' => ['2021-04-26', '2021-05-25'],
                ],
                [
                    'name' => '测试交付',
                    'data' => ['2021-05-26', '2021-05-30'],
                ],
                [
                    'name' => '项目上线',
                    'data' => ['2021-05-30', '2021-06-02'],
                ],
            ],
        ];
        $json['html'] = $this->gantt($data);
        return json_encode($json, 320);
    }

    /**
     * 工资曲线 - 返回数据
     */
    public function wagesData(): bool|string
    {
        $month = $this->post('months');
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = $this->date;
            $timeArr[1] = date('Y-m-d', strtotime("-12 month"));
        }
        $dataArr = self::dateRange($timeArr[0], $timeArr[1]);
        $name    = [];
        $xData   = [];
        foreach ($dataArr as $month) {
            $name[]  = $month;
            $result  = query('work_sign_record', "isPay = 1 and stid = '{$this->control['stid']}' and month = '$month'");
            $xData[] = $result['payMoney'];
        }
        $data         = [
            "name"   => $name,
            "series" => [
                [
                    'name' => '工资',
                    'data' => $xData,
                ],
            ],
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }


    /**
     * 订单与回款 数据
     *
     * @return string
     */
    public function orderData(): string
    {
        function calc($obj, $operator, $month)
        {
            $where = $obj->timeComparison($month, 'month', 'targetDate');
            return find([
                "table" => "record",
                'sum'   => "money",
                "where" => "type = '客户' AND classify $operator ('收款单核销', '核销') " . $where,
            ]);
        }

        $month = $this->post('months');
        if (!empty($month)) {
            $timeArr = explode(' ~ ', $month);
        } else {
            $timeArr[0] = $this->date;
            $timeArr[1] = date('Y-m-d', strtotime("-12 month"));
        }
        $monthArr = self::dateRange($timeArr[0], $timeArr[1]);
        $res      = [];
        foreach ($monthArr as $month) {
            $res[] = [
                'month'     => $month,
                'saleMoney' => calc($this, 'not in', $month),
                'recMoney'  => calc($this, 'in', $month),
            ];
        }
        $data         = [
            "name"   => array_column($res, 'month'),
            "series" => [
                [
                    'name' => '订单金额',
                    'data' => array_column($res, 'saleMoney'),
                ],
                [
                    'name' => '回款金额',
                    'data' => array_column($res, 'recMoney'),
                ],
            ],
        ];
        $json['html'] = $this->curve($data);
        return json_encode($json, 320);
    }


    /*日志量-页面*/
    public function logs(): string
    {
        //数据准备
        $endDay   = date("Y-m-d");                         //当前日期
        $startDay = date("Y-m-d", time() - 3600 * 24 * 30);//30天之前
        //生成页面
        //返回
        return "
        <li>
            <div>
                <form name='logDataForm' onsubmit=\"return searchFormSub('homepage','logData')\">日志量：" .
            text(array("name" => "startDay", "laydate" => [], "title" => "日期", "class" => "titleText", "value" => $startDay)) . "\n-\n" .
            text(array("name" => "endDay", "laydate" => [], "title" => "日期", "class" => "titleText", "value" => $endDay)) . "
                <input type='submit' value='查询' class='titleSub'>
                </form>
            </div>
            <div id='logDataHtml'>数据查询中。。。</div>
        </li>
        <script>$(function(){searchForm('homepage','logData',1)});</script>
        ";
    }

    /*日志量-返回数据*/
    public function logData(): bool|string
    {
        //查询最早的日志
        $earliestLog = query("log", "stid = '" . $this->control['stid'] . "' order by time ");
        //判断
        if (empty($this->post('startDay'))) {
            $json['html'] = "请填写开始日期";
        } elseif (empty($this->post('endDay'))) {
            $json['html'] = "请填写结束日期";
        } elseif (strtotime(date("Y-m-d", strtotime($earliestLog['time']))) > strtotime($this->post('startDay'))) {
            $json['html'] = $earliestLog['time'] . "前未查到你的任何日志记录";
        } elseif (strtotime($this->post('startDay')) > strtotime($this->post('endDay'))) {
            $json['html'] = "开始日期不能大于结束日期";
        } elseif (strtotime($this->post('endDay') . " 00:00:00") > time()) {
            $json['html'] = "结束日期不得大于当前日期";
        } else {
            //分析数据
            $list  = $log = [];
            $today = strtotime($this->post('startDay'));
            while ($today < strtotime($this->post('endDay'))) {
                $today     += 3600 * 24;
                $timeStart = date("Y-m-d", $today) . " 00:00:00";
                $timeEnd   = date("Y-m-d", $today) . " 23:59:59";
                $list[]    = date("Y-m-d", $today);
                $logSql    = find(array(
                    "table" => "log",
                    "where" => " stid = '" . $this->control['stid'] . "' and time >= '$timeStart' and time <= '$timeEnd'",
                ));
                $log[]     = $logSql['num'];
            }
            //生成json
            if (empty($json['html'])) {
                $json['html'] = $this->curve(array(
                    "name"   => $list,
                    "series" => array(
                        array(
                            "name" => "当天日志量",
                            "data" => $log,
                        ),
                    ),
                ));
            }
        }
        //返回
        return json_encode($json, 320);
    }

    /**
     * 判断所操作的数据是否是当前账套
     */
    public function preValidationCoid(): bool|string
    {
        $coid = $this->post('coid');
        if($coid == self::$coid || empty($coid)){
            $json['warn'] = 2;
        }else{
            $company = query('company', "coid = '$coid'", "name");
            $json['warn'] = "操作此数据需切换账套到【{$company['name']}】，切换账套后所有页卡将被关闭，是否确认切换账套？";
        }
        return json_encode($json, 320);
    }

    /**
     * 修改coid
     */
    public function updateCoid(): bool|string
    {
        $coid = $this->post('coid');
        if (empty($coid)) {
            $json['warn'] = '未找到此账套';
        } else {
            $company = query('company', "coid = '$coid'");
            if (empty($company['coid'])) {
                $json['warn'] = '未找到此账套';
            } elseif ($company['coid'] == self::$coid) {
                $json['warn'] = '当前正在使用，无需更换';
            } else {
                $bool = self::updateCoidRecord($coid);
                if ($bool) {
                    self::$coid = $coid;
                    $this->insertDefault();
                    $this->setDefaultSetting();
                    $json['warn'] = 2;
                } else {
                    $json['warn'] = '切换失败';
                }
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 获取临时内容
     *
     * @return string
     */
    function getTemp(): string
    {
        $cla  = $this->post('cla');
        $fun  = $this->post('fun');
        $resp = [];
        if (empty($cla) || empty($fun)) {
            $resp['warn'] = '参数错误';
        } else {
            $where        = generateWhere([
                'cla'  => $cla,
                'fun'  => $fun,
                'stid' => self::$stid,
            ]);
            $info         = query('content_temp', $where);
            $resp['warn'] = 2;
            $data         = [];
            if (!empty($info['text'])) {
                $temp  = static::htmlDecode($info['text']);
                $forms = json_decode($temp, true);
                parse_str($forms, $data);
            }
            $resp['data'] = $data;

        }

        return json_encode($resp, 320);
    }

    /**
     * 删除草稿内容
     *
     * @return void
     */
    function delTemp(): void
    {
        $str    = $this->post('str');
        $string = parse_url($str, PHP_URL_QUERY);
        parse_str(static::htmlDecode($string), $data);
        $where = [
            'cla'  => $data['cla'],
            'fun'  => substr($data['fun'], 0, strlen($data['fun']) - 4),
            'stid' => self::$stid,
        ];
        delete(['table' => 'content_temp', 'where' => generateWhere($where)]);
    }

    /**
     * 保存临时内容
     *
     * @return string
     */
    public function saveTemp(): string
    {
        $field      = [
            'cla'  => $this->post('cla'),
            'fun'  => $this->post('fun'),
            'text' => $this->post('body'),
            'stid' => static::$stid,
        ];
        $annotation = [
            'cla'  => '页面',
            'fun'  => '页面',
            'text' => '保存内容',
        ];
        $rules      = [
            'cla'  => 'required',
            'fun'  => 'required',
            'text' => 'required',
        ];
        // 校验是否符合规则
        $vt     = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if ($result === false) {
            $resp['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
        } else {
            $wField = $field;
            unset($wField['text']);
            $where = generateWhere($wField);
            $info  = query('content_temp', $where);
            if ($info['id']) {
                $json['warn'] = static::update([
                    'table' => 'content_temp',
                    'field' => ['text' => json_encode($field['text'], 320)],
                    'where' => $where,
                ]);
            } else {
                $field['id']   = static::getId();
                $field['text'] = json_encode($field['text'], 320);

                $json['warn'] = static::insert([
                    'table' => 'content_temp',
                    'field' => $field,
                ]);
            }
            if (!in_array($json['warn'], ['更新成功', '新增成功'])) {
                $resp['warn'] = '保存失败，未知错误' . $json['warn'];
                // $resp['warn'] = L('homepage.languageToggle.langErr');
            } else {
                $resp['warn']     = 2;
                $_SESSION['warn'] = '保存成功';
                // $_SESSION['warn'] = L('homepage.languageToggle.langSuss');
            }
        }

        resp:
        return json_encode($resp, 320);
    }

    /*
     * 切换语言
     */
    public function languageToggle(): string
    {
        $lang = $this->post('lang');
        if (!$lang) {
            // 参数错误
            $resp['warn'] = L('homepage.languageToggle.langErr');
        } else {
            $where = [
                'type' => '系统语言',
                'stid' => static::$stid,
            ];
            $info  = query('user_setting', generateWhere($where));
            if ($info['id']) {
                $json['warn'] = static::update([
                    'table' => 'user_setting',
                    'field' => ['value' => $lang],
                    'where' => generateWhere($where),
                ]);
            } else {
                $json['warn'] = static::insert([
                    'table' => 'user_setting',
                    'field' => array_merge($where, ['value' => $lang]),
                ]);
            }
            if (!in_array($json['warn'], ['更新成功', '新增成功'])) {
                $resp['warn'] = L('homepage.languageToggle.langErr');
            } else {
                $_SESSION['lang'] = $lang;
                $resp['warn']     = 2;
                $_SESSION['warn'] = L('homepage.languageToggle.langSuss');
            }
        }
        return json_encode($resp, 320);
    }

    /**
     * Desc :
     * User : you name
     * Date : 2023-09-11 11:03
     * @param $array
     */
    public function getThirdLevelKeys($array)
    {
        $result = [];
        foreach ($array as $value) {
            foreach ($value as $threeArray) {
                foreach ($threeArray as $fourArray) {
                    foreach ($fourArray as $k => $v) {
                        $result[] = $k;
                    }
                }

            }
        }
        return $result;
    }

    /**
     * 设置能展示的字段
     */
    public function setField(): string
    {
        $json['code'] = 0;
        $sourceClick  = $this->post('sourceClick');//点击事件来源 colWidth：宽度调整
        $fields       = $this->post('fields');
        $pageStr      = $this->post('page');
        $page         = explode('-', $pageStr)[0];
        $class        = $this->getThirdLevelKeys($GLOBALS['powerAll']);
        if (in_array($page, $class) && !$this->power($page, "see")) {
            $json['warn'] = "你没有{$page}页面的查看权限";
        } elseif (self::is_null_array($fields)) {
            $json['warn'] = '至少展示一个字段';
        } else {
            $wData = [
                'type' => '自定义显示字段',
                'page' => $pageStr,
                'stid' => self::$stid,
            ];
            $info  = query('user_setting', generateWhere($wData));
            // 判断类型
            $data['field'] = $fields;
            if ($info['id']) {
                $widths = json_decode($info['value'], true)['width'];
                foreach ($fields as $field) {
                    // 判断请求值是否存在
                    if (empty($this->post($field))) {
                        // 没有提交时
                        $widths[$field] = empty($widths[$field]) ? 0 : $widths[$field];
                    } else {
                        // 提交时
                        $widths[$field] = $this->post($field);
                    }
                }
                $data['width'] = $widths;
                // 表格宽度
                $json['warn'] = static::update([
                    'table' => 'user_setting',
                    'field' => ['value' => json_encode($data, 320)],
                    'where' => generateWhere($wData),
                ]);
            } else {
                $data['width'] = [];
                $json['warn']  = static::insert([
                    'table' => 'user_setting',
                    'field' => array_merge($wData, ['value' => json_encode($data, 320)]),
                ]);
            }
            if (in_array($json['warn'], ['更新成功', '新增成功'])) {
                $json['code'] = 1;
                if ($sourceClick != 'colWidth') {
                    $_SESSION['warn'] = '设置成功';
                }
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 获取左边二级菜单
     *
     */
    public function getMenuJson()
    {
        $menuJson = [];
        foreach ($this->powerAllLang as $menuOneName => $menuOneVal) {
            if (count(array_intersect_key(self::extractBottomArray(array_values($menuOneVal)), $this->controlPower)) > 0) {
                foreach ($menuOneVal as $menuTwoName => $menuTwoValue) {
                    if (count(array_intersect_key(self::extractBottomArray(array_values($menuTwoValue)), $this->controlPower)) > 0) {
                        $menuThreeJson = [];
                        foreach ($menuTwoValue as $menuThreeName => $menuThreeValue) {
                            if (count(array_intersect_key($menuThreeValue, $this->controlPower)) > 0) {

                                $menuFourJson = [];
                                foreach ($menuThreeValue as $menuFourName => $menuFourValue) {
                                    if (isset($this->controlPower[$menuFourName]) && count(array_intersect(array_keys((array)$menuFourValue), (array)$this->controlPower[$menuFourName])) > 0) {
                                        //链接
                                        if (empty($menuFourValue['cla']) or empty($menuFourValue['fun'])) {
                                            //如果没有定义类或函数名称，则使用模块名称作为类名称
                                            $iframeHref = "control/adIndex.html?cla=" . $menuFourName . "&fun=home";
                                        } else {
                                            $iframeHref = "control/adIndex.html?cla=" . $menuFourValue['cla'] . "&fun=" . $menuFourValue['fun'] . "&fourKey=" . $menuFourName;
                                        }
                                        //子菜单
                                        $iframeHref                  = root . $iframeHref;
                                        $menuFourValue['iframeHref'] = $iframeHref;
                                        $menuFourJson[]              = $menuFourValue;
                                    }
                                }
                                $menuThreeJson[] = [
                                    'name'     => $menuThreeName,
                                    'children' => $menuFourJson
                                ];
                            }
                        }
                        $menuJson[] = [
                            'menuOneName' => $menuOneName,
                            'menuTwoName' => $menuTwoName,
                            'children'    => $menuThreeJson
                        ];
                    }
                }
            }
        }
        $json['data'] = $menuJson;
        return json_encode($json, 320);
    }

    /**
     * 列表每页行数设置
     */
    public function setPageNum(): string
    {
        $json['code'] = 0;
        $num          = $this->post('num');
        $pageStr      = $this->post('pageStr');
        $page         = explode('-', $pageStr)[0];
        $class        = $this->getThirdLevelKeys($GLOBALS['powerAll']);
        if (in_array($page, $class) && !$this->power($page, "see")) {
            $json['warn'] = "你没有{$page}页面的查看权限";
        } elseif (preg_match(checkInteger, $num) == 0) {
            $json['warn'] = '行数必须为正整数';
        } elseif ($num < 0) {
            $json['warn'] = '行数必须大于零';
        } elseif ($num > 100) {
            $json['warn'] = '行数不能大于100';
        } else {
            $wData = [
                'type' => '每页行数',
                'page' => $pageStr,
                'stid' => self::$stid,
            ];
            $info  = query('user_setting', generateWhere($wData));
            if ($info['id']) {
                // 表格宽度
                $json['warn'] = static::update([
                    'table' => 'user_setting',
                    'field' => ['value' => $num],
                    'where' => generateWhere($wData),
                ]);
            } else {
                $json['warn'] = static::insert([
                    'table' => 'user_setting',
                    'field' => array_merge($wData, ['value' => $num]),
                ]);
            }
            if (in_array($json['warn'], ['更新成功', '新增成功'])) {
                $json['code'] = 1;
                $json['warn'] = '设置成功';
            }
        }
        return json_encode($json, 320);
    }


}
